summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.0.026
-rw-r--r--doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp2
-rw-r--r--doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp2
-rw-r--r--doc/src/snippets/qstring/main.cpp65
-rw-r--r--qmake/Makefile.unix6
-rw-r--r--qmake/Makefile.win321
-rw-r--r--qmake/Makefile.win32-g++1
-rw-r--r--qmake/qmake.pri1
-rw-r--r--src/corelib/global/qglobal.h6
-rw-r--r--src/corelib/io/io.pri3
-rw-r--r--src/corelib/io/qdatastream.h2
-rw-r--r--src/corelib/io/qdiriterator.h2
-rw-r--r--src/corelib/io/qfile.cpp635
-rw-r--r--src/corelib/io/qfile.h62
-rw-r--r--src/corelib/io/qfile_p.h20
-rw-r--r--src/corelib/io/qfiledevice.cpp736
-rw-r--r--src/corelib/io/qfiledevice.h147
-rw-r--r--src/corelib/io/qfiledevice_p.h104
-rw-r--r--src/corelib/io/qtextstream.cpp2
-rw-r--r--src/corelib/io/qurl.cpp31
-rw-r--r--src/corelib/io/qurl.h1
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h2
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h2
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.h2
-rw-r--r--src/corelib/json/qjsonvalue.cpp2
-rw-r--r--src/corelib/kernel/qmetaobject.cpp822
-rw-r--r--src/corelib/kernel/qmetaobject.h15
-rw-r--r--src/corelib/kernel/qmetaobject_p.h77
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp304
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h19
-rw-r--r--src/corelib/kernel/qmetatype.cpp78
-rw-r--r--src/corelib/kernel/qmetatype.h85
-rw-r--r--src/corelib/kernel/qmetatypeswitcher_p.h7
-rw-r--r--src/corelib/kernel/qobject.cpp266
-rw-r--r--src/corelib/kernel/qobjectdefs.h10
-rw-r--r--src/corelib/kernel/qvariant.cpp36
-rw-r--r--src/corelib/kernel/qvariant.h16
-rw-r--r--src/corelib/kernel/qvariant_p.h51
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp38
-rw-r--r--src/corelib/statemachine/qstatemachine.h2
-rw-r--r--src/corelib/tools/qarraydata.cpp111
-rw-r--r--src/corelib/tools/qarraydata.h275
-rw-r--r--src/corelib/tools/qarraydataops.h322
-rw-r--r--src/corelib/tools/qarraydatapointer.h220
-rw-r--r--src/corelib/tools/qbytearray.cpp159
-rw-r--r--src/corelib/tools/qbytearray.h69
-rw-r--r--src/corelib/tools/qhash.cpp4
-rw-r--r--src/corelib/tools/qhash.h4
-rw-r--r--src/corelib/tools/qlinkedlist.cpp2
-rw-r--r--src/corelib/tools/qlinkedlist.h22
-rw-r--r--src/corelib/tools/qlist.cpp24
-rw-r--r--src/corelib/tools/qlist.h60
-rw-r--r--src/corelib/tools/qmap.cpp4
-rw-r--r--src/corelib/tools/qmap.h6
-rw-r--r--src/corelib/tools/qrefcount.h58
-rw-r--r--src/corelib/tools/qregularexpression.h2
-rw-r--r--src/corelib/tools/qsharedpointer.cpp37
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h10
-rw-r--r--src/corelib/tools/qstring.cpp592
-rw-r--r--src/corelib/tools/qstring.h95
-rw-r--r--src/corelib/tools/qstringbuilder.h13
-rw-r--r--src/corelib/tools/qvector.cpp16
-rw-r--r--src/corelib/tools/qvector.h370
-rw-r--r--src/corelib/tools/tools.pri4
-rw-r--r--src/dbus/qdbus_symbols.cpp15
-rw-r--r--src/dbus/qdbusabstractadaptor.cpp61
-rw-r--r--src/dbus/qdbusabstractadaptor.h2
-rw-r--r--src/dbus/qdbusabstractinterface.cpp10
-rw-r--r--src/dbus/qdbusconnection.h2
-rw-r--r--src/dbus/qdbusconnection_p.h6
-rw-r--r--src/dbus/qdbuserror.cpp24
-rw-r--r--src/dbus/qdbuserror.h9
-rw-r--r--src/dbus/qdbusintegrator.cpp12
-rw-r--r--src/dbus/qdbusinterface.cpp4
-rw-r--r--src/dbus/qdbusmetaobject.cpp205
-rw-r--r--src/dbus/qdbusmetaobject_p.h3
-rw-r--r--src/dbus/qdbusmetatype.cpp28
-rw-r--r--src/dbus/qdbusmisc.cpp25
-rw-r--r--src/dbus/qdbuspendingcall.cpp2
-rw-r--r--src/dbus/qdbuspendingcall.h2
-rw-r--r--src/dbus/qdbuspendingcall_p.h2
-rw-r--r--src/dbus/qdbuspendingreply.h4
-rw-r--r--src/dbus/qdbusreply.cpp2
-rw-r--r--src/dbus/qdbusreply.h2
-rw-r--r--src/dbus/qdbusutil.cpp6
-rw-r--r--src/dbus/qdbusxmlgenerator.cpp2
-rw-r--r--src/gui/accessible/qaccessible2.h2
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp4
-rw-r--r--src/gui/image/qmovie.h2
-rw-r--r--src/gui/image/qpixmap.h4
-rw-r--r--src/gui/kernel/qclipboard.h2
-rw-r--r--src/gui/kernel/qevent.cpp26
-rw-r--r--src/gui/kernel/qevent.h19
-rw-r--r--src/gui/kernel/qevent_p.h2
-rw-r--r--src/gui/kernel/qkeysequence.cpp10
-rw-r--r--src/gui/kernel/qkeysequence.h3
-rw-r--r--src/gui/kernel/qopenglcontext.h2
-rw-r--r--src/gui/kernel/qplatformsharedgraphicscache_qpa.h2
-rw-r--r--src/gui/kernel/qplatformsurface_qpa.h2
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.h2
-rw-r--r--src/gui/kernel/qscreen.h2
-rw-r--r--src/gui/kernel/qsurface.h2
-rw-r--r--src/gui/kernel/qsurfaceformat.h2
-rw-r--r--src/gui/kernel/qwindow.h4
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa.h2
-rw-r--r--src/gui/math3d/qgenericmatrix.h2
-rw-r--r--src/gui/math3d/qmatrix4x4.h2
-rw-r--r--src/gui/opengl/qopenglframebufferobject.h2
-rw-r--r--src/gui/opengl/qopenglfunctions.h2
-rw-r--r--src/gui/opengl/qopenglpaintdevice.h2
-rw-r--r--src/gui/painting/qbackingstore.h2
-rw-r--r--src/gui/painting/qpdfwriter.h4
-rw-r--r--src/gui/painting/qplatformbackingstore_qpa.h2
-rw-r--r--src/gui/painting/qpolygon.h10
-rw-r--r--src/gui/text/qfont.h2
-rw-r--r--src/gui/text/qfontmetrics.cpp14
-rw-r--r--src/gui/text/qsyntaxhighlighter.h4
-rw-r--r--src/gui/text/qtextdocumentwriter.h2
-rw-r--r--src/gui/text/qtextlayout.cpp2
-rw-r--r--src/gui/text/qtextoption.h2
-rw-r--r--src/gui/util/qvalidator.h2
-rw-r--r--src/network/access/qhttpmultipart.h4
-rw-r--r--src/network/access/qnetworkcookie.h2
-rw-r--r--src/network/access/qnetworkcookiejar.h2
-rw-r--r--src/network/access/qnetworkreply.h2
-rw-r--r--src/network/kernel/qdnslookup.h2
-rw-r--r--src/network/kernel/qhostinfo.h2
-rw-r--r--src/network/kernel/qnetworkproxy.h4
-rw-r--r--src/network/socket/qlocalserver.h2
-rw-r--r--src/network/ssl/qsslcertificate.h4
-rw-r--r--src/network/ssl/qsslsocket.h2
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp2
-rw-r--r--src/printsupport/dialogs/qprintdialog.h2
-rw-r--r--src/printsupport/kernel/qprinterinfo.h4
-rw-r--r--src/sql/kernel/qsqlfield.h4
-rw-r--r--src/sql/kernel/qsqlindex.h2
-rw-r--r--src/sql/kernel/qsqlquery.h4
-rw-r--r--src/testlib/qsignaldumper.cpp7
-rw-r--r--src/testlib/qsignalspy.h4
-rw-r--r--src/testlib/qtest.h4
-rw-r--r--src/testlib/qtest_global.h5
-rw-r--r--src/testlib/qtest_gui.h4
-rw-r--r--src/testlib/qtestcase.cpp11
-rw-r--r--src/testlib/qtestcase.h20
-rw-r--r--src/tools/bootstrap/bootstrap.pro1
-rw-r--r--src/tools/moc/generator.cpp409
-rw-r--r--src/tools/moc/generator.h10
-rw-r--r--src/tools/moc/moc.cpp10
-rw-r--r--src/tools/moc/moc.h3
-rw-r--r--src/tools/moc/outputrevision.h2
-rw-r--r--src/tools/moc/preprocessor.cpp9
-rw-r--r--src/tools/moc/preprocessor.h2
-rw-r--r--src/widgets/dialogs/qdialog.h4
-rw-r--r--src/widgets/itemviews/qcolumnview_p.h2
-rw-r--r--src/widgets/itemviews/qdatawidgetmapper.h2
-rw-r--r--src/widgets/itemviews/qitemeditorfactory.h2
-rw-r--r--src/widgets/itemviews/qstandarditemmodel.h2
-rw-r--r--src/widgets/itemviews/qtablewidget.h2
-rw-r--r--src/widgets/itemviews/qtreewidget.h2
-rw-r--r--src/widgets/kernel/qstackedlayout.cpp32
-rw-r--r--src/widgets/kernel/qstackedlayout.h2
-rw-r--r--src/widgets/kernel/qwidget.cpp1
-rw-r--r--src/widgets/widgets/qstackedwidget.cpp46
-rw-r--r--src/widgets/widgets/qtabbar.cpp20
-rw-r--r--src/widgets/widgets/qtabbar.h1
-rw-r--r--src/widgets/widgets/qtabbar_p.h2
-rw-r--r--src/xml/sax/qxml.h2
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp20
-rw-r--r--tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp61
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp10
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp29
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp31
-rw-r--r--tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp2
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp16
-rw-r--r--tests/auto/corelib/kernel/qvariant/stream/qt5.0/qregularexpression.binbin0 -> 53 bytes
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp46
-rw-r--r--tests/auto/corelib/tools/qarraydata/qarraydata.pro5
-rw-r--r--tests/auto/corelib/tools/qarraydata/simplevector.h341
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp1464
-rw-r--r--tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp35
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp172
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp220
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp94
-rw-r--r--tests/auto/corelib/tools/tools.pro1
-rw-r--r--tests/auto/dbus/qdbusmetaobject/tst_qdbusmetaobject.cpp226
-rw-r--r--tests/auto/dbus/qdbuspendingreply/tst_qdbuspendingreply.cpp38
-rw-r--r--tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp2
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp26
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp2
-rw-r--r--tests/benchmarks/corelib/kernel/qmetaobject/main.cpp6
-rw-r--r--tests/benchmarks/corelib/tools/qvector/qrawvector.h58
-rw-r--r--tools/configure/Makefile.mingw1
-rw-r--r--tools/configure/Makefile.win322
-rw-r--r--tools/configure/configure.pro2
194 files changed, 8013 insertions, 2310 deletions
diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0
index 03dc414e7f..0fd7cffb2f 100644
--- a/dist/changes-5.0.0
+++ b/dist/changes-5.0.0
@@ -36,6 +36,13 @@ information about a particular change.
- QCoreApplication::translate() will no longer return the source text when
the translation is empty. Use lrelease -removeidentical for optimization.
+- QString and QByteArray constructors that take a size argument will now treat
+ negative sizes to indicate nul-terminated strings (a nul-terminated array of
+ QChar, in the case of QString). In Qt 4, negative sizes were ignored and
+ result in empty QString and QByteArray, respectively. The size argument to
+ those constructors now has a default value of -1, thus replacing the separate
+ constructors that did the same.
+
- Qt::escape() is deprecated (but can be enabled via
QT_DISABLE_DEPRECATED_BEFORE), use QString::toHtmlEscaped() instead.
@@ -51,6 +58,11 @@ information about a particular change.
* QMetaType::construct() has been renamed to QMetaType::create().
* QMetaType::unregisterType() has been removed.
+- QMetaMethod::signature() has been renamed to QMetaMethod::methodSignature(),
+ and the return type has been changed to QByteArray. This was done to be able
+ to generate the signature string on demand, rather than always storing it in
+ the meta-data.
+
- QTestLib:
* The plain-text, xml and lightxml test output formats have been changed to
show a test result for every row of test data in data-driven tests. In
@@ -567,6 +579,20 @@ Qt for Windows CE
QMetaType::User, which means that it points to the first registered custom
type, instead of a nonexistent type.
+- QMetaType
+
+ * Interpretation of QMetaType::Void was changed. Before, in some cases
+ it was returned as an invalid type id, but sometimes it was used as a valid
+ type (C++ "void"). In Qt5, new QMetaType::UnknownType was introduced to
+ distinguish between these two. QMetaType::UnknownType is an invalid type id
+ signaling that a type is unknown to QMetaType, and QMetaType::Void
+ is a valid type id of C++ void type. The difference will be visible for
+ example in call to QMetaType::typeName(), this function will return null for
+ QMetaType::UnknownType and a pointer to "void" string for
+ QMetaType::Void.
+ Please, notice that QMetaType::UnknownType has value 0, which previously was
+ reserved for QMetaType::Void.
+
- QMessageBox
diff --git a/doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp b/doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp
index afba3b6a61..7c0c2c2122 100644
--- a/doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp
+++ b/doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp
@@ -107,7 +107,7 @@ for(int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i)
const QMetaObject* metaObject = obj->metaObject();
QStringList methods;
for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
- methods << QString::fromLatin1(metaObject->method(i).signature());
+ methods << QString::fromLatin1(metaObject->method(i).methodSignature());
//! [methodCount]
//! [6]
diff --git a/doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp b/doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp
index 9d72c42504..d0a7a69884 100644
--- a/doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp
+++ b/doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp
@@ -73,7 +73,7 @@ MyStruct s2 = var.value<MyStruct>();
//! [3]
int id = QMetaType::type("MyClass");
-if (id != 0) {
+if (id != QMetaType::UnknownType) {
void *myClassPtr = QMetaType::create(id);
...
QMetaType::destroy(id, myClassPtr);
diff --git a/doc/src/snippets/qstring/main.cpp b/doc/src/snippets/qstring/main.cpp
index d0a445731c..d7299e80d5 100644
--- a/doc/src/snippets/qstring/main.cpp
+++ b/doc/src/snippets/qstring/main.cpp
@@ -314,6 +314,11 @@ void Widget::countFunction()
QString str = "banana and panama";
str.count(QRegExp("a[nm]a")); // returns 4
//! [18]
+
+ //! [95]
+ QString str = "banana and panama";
+ str.count(QRegularExpression("a[nm]a")); // returns 4
+ //! [95]
}
void Widget::dataFunction()
@@ -384,6 +389,11 @@ void Widget::firstIndexOfFunction()
QString str = "the minimum";
str.indexOf(QRegExp("m[aeiou]"), 0); // returns 4
//! [25]
+
+ //! [93]
+ QString str = "the minimum";
+ str.indexOf(QRegularExpression("m[aeiou]"), 0); // returns 4
+ //! [93]
}
void Widget::insertFunction()
@@ -429,6 +439,11 @@ void Widget::lastIndexOfFunction()
QString str = "the minimum";
str.lastIndexOf(QRegExp("m[aeiou]")); // returns 8
//! [30]
+
+ //! [94]
+ QString str = "the minimum";
+ str.lastIndexOf(QRegularExpression("m[aeiou]")); // returns 8
+ //! [94]
}
void Widget::leftFunction()
@@ -499,6 +514,12 @@ void Widget::removeFunction()
r.remove(QRegExp("[aeiou]."));
// r == "The"
//! [39]
+
+ //! [96]
+ QString r = "Telephone";
+ r.remove(QRegularExpression("[aeiou]."));
+ // r == "The"
+ //! [96]
}
void Widget::replaceFunction()
@@ -533,6 +554,18 @@ void Widget::replaceFunction()
equis.replace("xx", "x");
// equis == "xxx"
//! [86]
+
+ //! [87]
+ QString s = "Banana";
+ s.replace(QRegularExpression("a[mn]"), "ox");
+ // s == "Boxoxa"
+ //! [87]
+
+ //! [88]
+ QString t = "A <i>bon mot</i>.";
+ t.replace(QRegularExpression("<i>([^<]*)</i>"), "\\emph{\\1}");
+ // t == "A \\emph{bon mot}."
+ //! [88]
}
void Widget::reserveFunction()
@@ -627,9 +660,16 @@ void Widget::sectionFunction()
//! [55]
QString line = "forename\tmiddlename surname \t \t phone";
QRegExp sep("\\s+");
- str = line.section(sep, 2, 2); // s == "surname"
- str = line.section(sep, -3, -2); // s == "middlename surname"
+ str = line.section(sep, 2, 2); // str == "surname"
+ str = line.section(sep, -3, -2); // str == "middlename surname"
//! [55]
+
+ //! [89]
+ QString line = "forename\tmiddlename surname \t \t phone";
+ QRegularExpression sep("\\s+");
+ str = line.section(sep, 2, 2); // str == "surname"
+ str = line.section(sep, -3, -2); // str == "middlename surname"
+ //! [89]
}
void Widget::setNumFunction()
@@ -682,6 +722,27 @@ void Widget::splitFunction()
list = str.split(QRegExp("\\b"));
// list: [ "", "Now", ": ", "this", " ", "sentence", " ", "fragment", "." ]
//! [61]
+
+ //! [90]
+ QString str;
+ QStringList list;
+
+ str = "Some text\n\twith strange whitespace.";
+ list = str.split(QRegularExpression("\\s+"));
+ // list: [ "Some", "text", "with", "strange", "whitespace." ]
+ //! [90]
+
+ //! [91]
+ str = "This time, a normal English sentence.";
+ list = str.split(QRegularExpression("\\W+"), QString::SkipEmptyParts);
+ // list: [ "This", "time", "a", "normal", "English", "sentence" ]
+ //! [91]
+
+ //! [92]
+ str = "Now: this sentence fragment.";
+ list = str.split(QRegularExpression("\\b"));
+ // list: [ "", "Now", ": ", "this", " ", "sentence", " ", "fragment", "." ]
+ //! [92]
}
void Widget::splitCaseSensitiveFunction()
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 03a8597eff..ab9b583ad3 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -17,7 +17,7 @@ OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \
#qt code
QOBJS=qtextcodec.o qutfcodec.o qstring.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \
- qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfile.o \
+ qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \
qfilesystementry.o qfilesystemengine_unix.o qfilesystemengine.o qfilesystemiterator_unix.o \
qfsfileengine_unix.o qfsfileengine.o \
qfsfileengine_iterator.o qregexp.o qvector.o qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o \
@@ -39,6 +39,7 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge
generators/integrity/gbuild.cpp \
$(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
$(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
$(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
@@ -245,6 +246,9 @@ qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp
+qfiledevice.o: $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
+
qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 89444c9c3c..adcfb040ed 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -84,6 +84,7 @@ QTOBJS= \
qdatetime.obj \
qdir.obj \
qdiriterator.obj \
+ qfiledevice.obj \
qfile.obj \
qtemporaryfile.obj \
qabstractfileengine.obj \
diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++
index 95108b351b..75c7e02334 100644
--- a/qmake/Makefile.win32-g++
+++ b/qmake/Makefile.win32-g++
@@ -82,6 +82,7 @@ QTOBJS= \
qdatetime.o \
qdir.o \
qdiriterator.o \
+ qfiledevice.o \
qfile.o \
qtemporaryfile.o \
qfileinfo.o \
diff --git a/qmake/qmake.pri b/qmake/qmake.pri
index fb530a6380..b8b9d43035 100644
--- a/qmake/qmake.pri
+++ b/qmake/qmake.pri
@@ -41,6 +41,7 @@ bootstrap { #Qt code
qdatetime.cpp \
qdir.cpp \
qdiriterator.cpp \
+ qfiledevice.cpp \
qfile.cpp \
qabstractfileengine.cpp \
qfileinfo.cpp \
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 99328d52ac..d0d6e851ad 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -415,9 +415,15 @@ QT_END_INCLUDE_NAMESPACE
#ifdef Q_COMPILER_EXPLICIT_OVERRIDES
# define Q_DECL_OVERRIDE override
# define Q_DECL_FINAL final
+# ifdef Q_COMPILER_DECLTYPE // required for class-level final to compile in qvariant_p.h
+# define Q_DECL_FINAL_CLASS final
+# else
+# define Q_DECL_FINAL_CLASS
+# endif
#else
# define Q_DECL_OVERRIDE
# define Q_DECL_FINAL
+# define Q_DECL_FINAL_CLASS
#endif
//defines the type for the WNDPROC on windows
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 29599295ad..9c117abe03 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -11,6 +11,8 @@ HEADERS += \
io/qdir_p.h \
io/qdiriterator.h \
io/qfile.h \
+ io/qfiledevice.h \
+ io/qfiledevice_p.h \
io/qfileinfo.h \
io/qfileinfo_p.h \
io/qiodevice.h \
@@ -49,6 +51,7 @@ SOURCES += \
io/qdir.cpp \
io/qdiriterator.cpp \
io/qfile.cpp \
+ io/qfiledevice.cpp \
io/qfileinfo.cpp \
io/qiodevice.cpp \
io/qnoncontiguousbytedevice.cpp \
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 752246a543..451a7ab959 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -114,7 +114,7 @@ public:
explicit QDataStream(QIODevice *);
QDataStream(QByteArray *, QIODevice::OpenMode flags);
QDataStream(const QByteArray &);
- virtual ~QDataStream();
+ ~QDataStream();
QIODevice *device() const;
void setDevice(QIODevice *);
diff --git a/src/corelib/io/qdiriterator.h b/src/corelib/io/qdiriterator.h
index 27189e2efd..d2d0645916 100644
--- a/src/corelib/io/qdiriterator.h
+++ b/src/corelib/io/qdiriterator.h
@@ -70,7 +70,7 @@ public:
QDir::Filters filters = QDir::NoFilter,
IteratorFlags flags = NoIteratorFlags);
- virtual ~QDirIterator();
+ ~QDirIterator();
QString next();
bool hasNext() const;
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 6640dca70b..433d4493e5 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -59,8 +59,6 @@
QT_BEGIN_NAMESPACE
-static const int QFILE_WRITEBUFFER_SIZE = 16384;
-
static QByteArray locale_encode(const QString &f)
{
#if defined(Q_OS_DARWIN)
@@ -86,16 +84,11 @@ QFile::EncoderFn QFilePrivate::encoder = locale_encode;
QFile::DecoderFn QFilePrivate::decoder = locale_decode;
QFilePrivate::QFilePrivate()
- : fileEngine(0), lastWasWrite(false),
- writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
- cachedSize(0)
{
}
QFilePrivate::~QFilePrivate()
{
- delete fileEngine;
- fileEngine = 0;
}
bool
@@ -137,39 +130,6 @@ QAbstractFileEngine *QFilePrivate::engine() const
return fileEngine;
}
-inline bool QFilePrivate::ensureFlushed() const
-{
- // This function ensures that the write buffer has been flushed (const
- // because certain const functions need to call it.
- if (lastWasWrite) {
- const_cast<QFilePrivate *>(this)->lastWasWrite = false;
- if (!const_cast<QFile *>(q_func())->flush())
- return false;
- }
- return true;
-}
-
-void
-QFilePrivate::setError(QFile::FileError err)
-{
- error = err;
- errorString.clear();
-}
-
-void
-QFilePrivate::setError(QFile::FileError err, const QString &errStr)
-{
- error = err;
- errorString = errStr;
-}
-
-void
-QFilePrivate::setError(QFile::FileError err, int errNum)
-{
- error = err;
- errorString = qt_error_string(errNum);
-}
-
//************* QFile
/*!
@@ -278,98 +238,18 @@ QFilePrivate::setError(QFile::FileError err, int errNum)
\sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System}
*/
-/*!
- \enum QFile::FileError
-
- This enum describes the errors that may be returned by the error()
- function.
-
- \value NoError No error occurred.
- \value ReadError An error occurred when reading from the file.
- \value WriteError An error occurred when writing to the file.
- \value FatalError A fatal error occurred.
- \value ResourceError
- \value OpenError The file could not be opened.
- \value AbortError The operation was aborted.
- \value TimeOutError A timeout occurred.
- \value UnspecifiedError An unspecified error occurred.
- \value RemoveError The file could not be removed.
- \value RenameError The file could not be renamed.
- \value PositionError The position in the file could not be changed.
- \value ResizeError The file could not be resized.
- \value PermissionsError The file could not be accessed.
- \value CopyError The file could not be copied.
-
- \omitvalue ConnectError
-*/
-
-/*!
- \enum QFile::Permission
-
- This enum is used by the permission() function to report the
- permissions and ownership of a file. The values may be OR-ed
- together to test multiple permissions and ownership values.
-
- \value ReadOwner The file is readable by the owner of the file.
- \value WriteOwner The file is writable by the owner of the file.
- \value ExeOwner The file is executable by the owner of the file.
- \value ReadUser The file is readable by the user.
- \value WriteUser The file is writable by the user.
- \value ExeUser The file is executable by the user.
- \value ReadGroup The file is readable by the group.
- \value WriteGroup The file is writable by the group.
- \value ExeGroup The file is executable by the group.
- \value ReadOther The file is readable by anyone.
- \value WriteOther The file is writable by anyone.
- \value ExeOther The file is executable by anyone.
-
- \warning Because of differences in the platforms supported by Qt,
- the semantics of ReadUser, WriteUser and ExeUser are
- platform-dependent: On Unix, the rights of the owner of the file
- are returned and on Windows the rights of the current user are
- returned. This behavior might change in a future Qt version.
-
- Note that Qt does not by default check for permissions on NTFS
- file systems, as this may decrease the performance of file
- handling considerably. It is possible to force permission checking
- on NTFS by including the following code in your source:
-
- \snippet doc/src/snippets/ntfsp.cpp 0
-
- Permission checking is then turned on and off by incrementing and
- decrementing \c qt_ntfs_permission_lookup by 1.
-
- \snippet doc/src/snippets/ntfsp.cpp 1
-*/
-
-/*!
- \enum QFile::FileHandleFlag
-
- This enum is used when opening a file to specify additional
- options which only apply to files and not to a generic
- QIODevice.
-
- \value AutoCloseHandle The file handle passed into open() should be
- closed by close(), the default behavior is that close just flushes
- the file and the application is responsible for closing the file handle.
- When opening a file by name, this flag is ignored as Qt always owns the
- file handle and must close it.
- \value DontCloseHandle If not explicitly closed, the underlying file
- handle is left open when the QFile object is destroyed.
- */
-
#ifdef QT_NO_QOBJECT
QFile::QFile()
- : QIODevice(*new QFilePrivate)
+ : QFileDevice(*new QFilePrivate)
{
}
QFile::QFile(const QString &name)
- : QIODevice(*new QFilePrivate)
+ : QFileDevice(*new QFilePrivate)
{
d_func()->fileName = name;
}
QFile::QFile(QFilePrivate &dd)
- : QIODevice(dd)
+ : QFileDevice(dd)
{
}
#else
@@ -377,21 +257,21 @@ QFile::QFile(QFilePrivate &dd)
\internal
*/
QFile::QFile()
- : QIODevice(*new QFilePrivate, 0)
+ : QFileDevice(*new QFilePrivate, 0)
{
}
/*!
Constructs a new file object with the given \a parent.
*/
QFile::QFile(QObject *parent)
- : QIODevice(*new QFilePrivate, parent)
+ : QFileDevice(*new QFilePrivate, parent)
{
}
/*!
Constructs a new file object to represent the file with the given \a name.
*/
QFile::QFile(const QString &name)
- : QIODevice(*new QFilePrivate, 0)
+ : QFileDevice(*new QFilePrivate, 0)
{
Q_D(QFile);
d->fileName = name;
@@ -401,7 +281,7 @@ QFile::QFile(const QString &name)
file with the specified \a name.
*/
QFile::QFile(const QString &name, QObject *parent)
- : QIODevice(*new QFilePrivate, parent)
+ : QFileDevice(*new QFilePrivate, parent)
{
Q_D(QFile);
d->fileName = name;
@@ -410,7 +290,7 @@ QFile::QFile(const QString &name, QObject *parent)
\internal
*/
QFile::QFile(QFilePrivate &dd, QObject *parent)
- : QIODevice(dd, parent)
+ : QFileDevice(dd, parent)
{
}
#endif
@@ -420,7 +300,6 @@ QFile::QFile(QFilePrivate &dd, QObject *parent)
*/
QFile::~QFile()
{
- close();
}
/*!
@@ -962,20 +841,6 @@ QFile::copy(const QString &fileName, const QString &newName)
}
/*!
- Returns true if the file can only be manipulated sequentially;
- otherwise returns false.
-
- Most files support random-access, but some special files may not.
-
- \sa QIODevice::isSequential()
-*/
-bool QFile::isSequential() const
-{
- Q_D(const QFile);
- return d->fileEngine && d->fileEngine->isSequential();
-}
-
-/*!
Opens the file using OpenMode \a mode, returning true if successful;
otherwise false.
@@ -1149,119 +1014,11 @@ bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
}
/*!
- Returns the file handle of the file.
-
- This is a small positive integer, suitable for use with C library
- functions such as fdopen() and fcntl(). On systems that use file
- descriptors for sockets (i.e. Unix systems, but not Windows) the handle
- can be used with QSocketNotifier as well.
-
- If the file is not open, or there is an error, handle() returns -1.
-
- This function is not supported on Windows CE.
-
- \sa QSocketNotifier
-*/
-
-int
-QFile::handle() const
-{
- Q_D(const QFile);
- if (!isOpen() || !d->fileEngine)
- return -1;
-
- return d->fileEngine->handle();
-}
-
-/*!
- \enum QFile::MemoryMapFlags
- \since 4.4
-
- This enum describes special options that may be used by the map()
- function.
-
- \value NoOptions No options.
-*/
-
-/*!
- \since 4.4
- Maps \a size bytes of the file into memory starting at \a offset. A file
- should be open for a map to succeed but the file does not need to stay
- open after the memory has been mapped. When the QFile is destroyed
- or a new file is opened with this object, any maps that have not been
- unmapped will automatically be unmapped.
-
- Any mapping options can be passed through \a flags.
-
- Returns a pointer to the memory or 0 if there is an error.
-
- \note On Windows CE 5.0 the file will be closed before mapping occurs.
-
- \sa unmap()
- */
-uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags)
-{
- Q_D(QFile);
- if (d->engine()
- && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
- unsetError();
- uchar *address = d->fileEngine->map(offset, size, flags);
- if (address == 0)
- d->setError(d->fileEngine->error(), d->fileEngine->errorString());
- return address;
- }
- return 0;
-}
-
-/*!
- \since 4.4
- Unmaps the memory \a address.
-
- Returns true if the unmap succeeds; false otherwise.
-
- \sa map()
- */
-bool QFile::unmap(uchar *address)
-{
- Q_D(QFile);
- if (d->engine()
- && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
- unsetError();
- bool success = d->fileEngine->unmap(address);
- if (!success)
- d->setError(d->fileEngine->error(), d->fileEngine->errorString());
- return success;
- }
- d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
- return false;
-}
-
-/*!
- Sets the file size (in bytes) \a sz. Returns true if the file if the
- resize succeeds; false otherwise. If \a sz is larger than the file
- currently is the new bytes will be set to 0, if \a sz is smaller the
- file is simply truncated.
-
- \sa size(), setFileName()
+ \reimp
*/
-
-bool
-QFile::resize(qint64 sz)
+bool QFile::resize(qint64 sz)
{
- Q_D(QFile);
- if (!d->ensureFlushed())
- return false;
- d->engine();
- if (isOpen() && d->fileEngine->pos() > sz)
- seek(sz);
- if(d->fileEngine->setSize(sz)) {
- unsetError();
- d->cachedSize = sz;
- return true;
- }
- d->cachedSize = 0;
- d->setError(QFile::ResizeError, d->fileEngine->errorString());
- return false;
+ return QFileDevice::resize(sz); // for now
}
/*!
@@ -1282,18 +1039,11 @@ QFile::resize(const QString &fileName, qint64 sz)
}
/*!
- Returns the complete OR-ed together combination of
- QFile::Permission for the file.
-
- \sa setPermissions(), setFileName()
+ \reimp
*/
-
-QFile::Permissions
-QFile::permissions() const
+QFile::Permissions QFile::permissions() const
{
- Q_D(const QFile);
- QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
- return QFile::Permissions((int)perms); //ewww
+ return QFileDevice::permissions(); // for now
}
/*!
@@ -1317,16 +1067,9 @@ QFile::permissions(const QString &fileName)
\sa permissions(), setFileName()
*/
-bool
-QFile::setPermissions(Permissions permissions)
+bool QFile::setPermissions(Permissions permissions)
{
- Q_D(QFile);
- if (d->engine()->setPermissions(permissions)) {
- unsetError();
- return true;
- }
- d->setError(QFile::PermissionsError, d->fileEngine->errorString());
- return false;
+ return QFileDevice::setPermissions(permissions); // for now
}
/*!
@@ -1341,354 +1084,12 @@ QFile::setPermissions(const QString &fileName, Permissions permissions)
return QFile(fileName).setPermissions(permissions);
}
-static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
-{
- qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize());
- if (ret > 0)
- buffer->free(ret);
- return ret;
-}
-
-/*!
- Flushes any buffered data to the file. Returns true if successful;
- otherwise returns false.
-*/
-
-bool
-QFile::flush()
-{
- Q_D(QFile);
- if (!d->fileEngine) {
- qWarning("QFile::flush: No file engine. Is IODevice open?");
- return false;
- }
-
- if (!d->writeBuffer.isEmpty()) {
- qint64 size = d->writeBuffer.size();
- if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) {
- QFile::FileError err = d->fileEngine->error();
- if(err == QFile::UnspecifiedError)
- err = QFile::WriteError;
- d->setError(err, d->fileEngine->errorString());
- return false;
- }
- }
-
- if (!d->fileEngine->flush()) {
- QFile::FileError err = d->fileEngine->error();
- if(err == QFile::UnspecifiedError)
- err = QFile::WriteError;
- d->setError(err, d->fileEngine->errorString());
- return false;
- }
- return true;
-}
-
-/*!
- Calls QFile::flush() and closes the file. Errors from flush are ignored.
-
- \sa QIODevice::close()
-*/
-void
-QFile::close()
-{
- Q_D(QFile);
- if(!isOpen())
- return;
- bool flushed = flush();
- QIODevice::close();
-
- // reset write buffer
- d->lastWasWrite = false;
- d->writeBuffer.clear();
-
- // keep earlier error from flush
- if (d->fileEngine->close() && flushed)
- unsetError();
- else if (flushed)
- d->setError(d->fileEngine->error(), d->fileEngine->errorString());
-}
-
-/*!
- Returns the size of the file.
-
- For regular empty files on Unix (e.g. those in \c /proc), this function
- returns 0; the contents of such a file are generated on demand in response
- to you calling read().
-*/
-
-qint64 QFile::size() const
-{
- Q_D(const QFile);
- if (!d->ensureFlushed())
- return 0;
- d->cachedSize = d->engine()->size();
- return d->cachedSize;
-}
-
-/*!
- \reimp
-*/
-
-qint64 QFile::pos() const
-{
- return QIODevice::pos();
-}
-
-/*!
- Returns true if the end of the file has been reached; otherwise returns
- false.
-
- For regular empty files on Unix (e.g. those in \c /proc), this function
- returns true, since the file system reports that the size of such a file is
- 0. Therefore, you should not depend on atEnd() when reading data from such a
- file, but rather call read() until no more data can be read.
-*/
-
-bool QFile::atEnd() const
-{
- Q_D(const QFile);
-
- // If there's buffered data left, we're not at the end.
- if (!d->buffer.isEmpty())
- return false;
-
- if (!isOpen())
- return true;
-
- if (!d->ensureFlushed())
- return false;
-
- // If the file engine knows best, say what it says.
- if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
- // Check if the file engine supports AtEndExtension, and if it does,
- // check if the file engine claims to be at the end.
- return d->fileEngine->atEnd();
- }
-
- // if it looks like we are at the end, or if size is not cached,
- // fall through to bytesAvailable() to make sure.
- if (pos() < d->cachedSize)
- return false;
-
- // Fall back to checking how much is available (will stat files).
- return bytesAvailable() == 0;
-}
-
-/*!
- \fn bool QFile::seek(qint64 pos)
-
- For random-access devices, this function sets the current position
- to \a pos, returning true on success, or false if an error occurred.
- For sequential devices, the default behavior is to do nothing and
- return false.
-
- Seeking beyond the end of a file:
- If the position is beyond the end of a file, then seek() shall not
- immediately extend the file. If a write is performed at this position,
- then the file shall be extended. The content of the file between the
- previous end of file and the newly written data is UNDEFINED and
- varies between platforms and file systems.
-*/
-
-bool QFile::seek(qint64 off)
-{
- Q_D(QFile);
- if (!isOpen()) {
- qWarning("QFile::seek: IODevice is not open");
- return false;
- }
-
- if (!d->ensureFlushed())
- return false;
-
- if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
- QFile::FileError err = d->fileEngine->error();
- if(err == QFile::UnspecifiedError)
- err = QFile::PositionError;
- d->setError(err, d->fileEngine->errorString());
- return false;
- }
- unsetError();
- return true;
-}
-
-/*!
- \reimp
-*/
-qint64 QFile::readLineData(char *data, qint64 maxlen)
-{
- Q_D(QFile);
- if (!d->ensureFlushed())
- return -1;
-
- qint64 read;
- if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
- read = d->fileEngine->readLine(data, maxlen);
- } else {
- // Fall back to QIODevice's readLine implementation if the engine
- // cannot do it faster.
- read = QIODevice::readLineData(data, maxlen);
- }
-
- if (read < maxlen) {
- // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
- d->cachedSize = 0;
- }
-
- return read;
-}
-
-/*!
- \reimp
-*/
-
-qint64 QFile::readData(char *data, qint64 len)
-{
- Q_D(QFile);
- unsetError();
- if (!d->ensureFlushed())
- return -1;
-
- qint64 read = d->fileEngine->read(data, len);
- if(read < 0) {
- QFile::FileError err = d->fileEngine->error();
- if(err == QFile::UnspecifiedError)
- err = QFile::ReadError;
- d->setError(err, d->fileEngine->errorString());
- }
-
- if (read < len) {
- // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
- d->cachedSize = 0;
- }
-
- return read;
-}
-
-/*!
- \internal
-*/
-bool QFilePrivate::putCharHelper(char c)
-{
-#ifdef QT_NO_QOBJECT
- return QIODevicePrivate::putCharHelper(c);
-#else
-
- // Cutoff for code that doesn't only touch the buffer.
- int writeBufferSize = writeBuffer.size();
- if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
-#ifdef Q_OS_WIN
- || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
-#endif
- ) {
- return QIODevicePrivate::putCharHelper(c);
- }
-
- if (!(openMode & QIODevice::WriteOnly)) {
- if (openMode == QIODevice::NotOpen)
- qWarning("QIODevice::putChar: Closed device");
- else
- qWarning("QIODevice::putChar: ReadOnly device");
- return false;
- }
-
- // Make sure the device is positioned correctly.
- const bool sequential = isSequential();
- if (pos != devicePos && !sequential && !q_func()->seek(pos))
- return false;
-
- lastWasWrite = true;
-
- int len = 1;
-#ifdef Q_OS_WIN
- if ((openMode & QIODevice::Text) && c == '\n') {
- ++len;
- *writeBuffer.reserve(1) = '\r';
- }
-#endif
-
- // Write to buffer.
- *writeBuffer.reserve(1) = c;
-
- if (!sequential) {
- pos += len;
- devicePos += len;
- if (!buffer.isEmpty())
- buffer.skip(len);
- }
-
- return true;
-#endif
-}
-
/*!
\reimp
*/
-
-qint64
-QFile::writeData(const char *data, qint64 len)
-{
- Q_D(QFile);
- unsetError();
- d->lastWasWrite = true;
- bool buffered = !(d->openMode & Unbuffered);
-
- // Flush buffered data if this read will overflow.
- if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
- if (!flush())
- return -1;
- }
-
- // Write directly to the engine if the block size is larger than
- // the write buffer size.
- if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
- qint64 ret = d->fileEngine->write(data, len);
- if(ret < 0) {
- QFile::FileError err = d->fileEngine->error();
- if(err == QFile::UnspecifiedError)
- err = QFile::WriteError;
- d->setError(err, d->fileEngine->errorString());
- }
- return ret;
- }
-
- // Write to the buffer.
- char *writePointer = d->writeBuffer.reserve(len);
- if (len == 1)
- *writePointer = *data;
- else
- ::memcpy(writePointer, data, len);
- return len;
-}
-
-/*!
- Returns the file error status.
-
- The I/O device status returns an error code. For example, if open()
- returns false, or a read/write operation returns -1, this function can
- be called to find out the reason why the operation failed.
-
- \sa unsetError()
-*/
-
-QFile::FileError
-QFile::error() const
-{
- Q_D(const QFile);
- return d->error;
-}
-
-/*!
- Sets the file's error to QFile::NoError.
-
- \sa error()
-*/
-void
-QFile::unsetError()
+qint64 QFile::size() const
{
- Q_D(QFile);
- d->setError(QFile::NoError);
+ return QFileDevice::size(); // for now
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index 7f370d4214..0ee8f39d95 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -42,7 +42,7 @@
#ifndef QFILE_H
#define QFILE_H
-#include <QtCore/qiodevice.h>
+#include <QtCore/qfiledevice.h>
#include <QtCore/qstring.h>
#include <stdio.h>
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
class QTemporaryFile;
class QFilePrivate;
-class Q_CORE_EXPORT QFile : public QIODevice
+class Q_CORE_EXPORT QFile : public QFileDevice
{
#ifndef QT_NO_QOBJECT
Q_OBJECT
@@ -65,39 +65,6 @@ class Q_CORE_EXPORT QFile : public QIODevice
Q_DECLARE_PRIVATE(QFile)
public:
-
- enum FileError {
- NoError = 0,
- ReadError = 1,
- WriteError = 2,
- FatalError = 3,
- ResourceError = 4,
- OpenError = 5,
- AbortError = 6,
- TimeOutError = 7,
- UnspecifiedError = 8,
- RemoveError = 9,
- RenameError = 10,
- PositionError = 11,
- ResizeError = 12,
- PermissionsError = 13,
- CopyError = 14
- };
-
- enum Permission {
- ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000,
- ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100,
- ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010,
- ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001
- };
- Q_DECLARE_FLAGS(Permissions, Permission)
-
- enum FileHandleFlag {
- AutoCloseHandle = 0x0001,
- DontCloseHandle = 0
- };
- Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag)
-
QFile();
QFile(const QString &name);
#ifndef QT_NO_QOBJECT
@@ -106,9 +73,6 @@ public:
#endif
~QFile();
- FileError error() const;
- void unsetError();
-
QString fileName() const;
void setFileName(const QString &name);
@@ -141,18 +105,11 @@ public:
bool copy(const QString &newName);
static bool copy(const QString &fileName, const QString &newName);
- bool isSequential() const;
-
bool open(OpenMode flags);
bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle);
- virtual void close();
qint64 size() const;
- qint64 pos() const;
- bool seek(qint64 offset);
- bool atEnd() const;
- bool flush();
bool resize(qint64 sz);
static bool resize(const QString &filename, qint64 sz);
@@ -162,15 +119,6 @@ public:
bool setPermissions(Permissions permissionSpec);
static bool setPermissions(const QString &filename, Permissions permissionSpec);
- int handle() const;
-
- enum MemoryMapFlags {
- NoOptions = 0
- };
-
- uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
- bool unmap(uchar *address);
-
protected:
#ifdef QT_NO_QOBJECT
QFile(QFilePrivate &dd);
@@ -178,17 +126,11 @@ protected:
QFile(QFilePrivate &dd, QObject *parent = 0);
#endif
- qint64 readData(char *data, qint64 maxlen);
- qint64 writeData(const char *data, qint64 len);
- qint64 readLineData(char *data, qint64 maxlen);
-
private:
friend class QTemporaryFile;
Q_DISABLE_COPY(QFile)
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QFile::Permissions)
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index 3d2d3d678b..575d7d14b9 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -53,15 +53,13 @@
// We mean it.
//
-#include "private/qabstractfileengine_p.h"
-#include "private/qiodevice_p.h"
-#include "private/qringbuffer_p.h"
+#include "private/qfiledevice_p.h"
QT_BEGIN_NAMESPACE
class QTemporaryFile;
-class QFilePrivate : public QIODevicePrivate
+class QFilePrivate : public QFileDevicePrivate
{
Q_DECLARE_PUBLIC(QFile)
friend class QTemporaryFile;
@@ -76,20 +74,6 @@ protected:
virtual QAbstractFileEngine *engine() const;
QString fileName;
- mutable QAbstractFileEngine *fileEngine;
-
- bool lastWasWrite;
- QRingBuffer writeBuffer;
- inline bool ensureFlushed() const;
-
- bool putCharHelper(char c);
-
- QFile::FileError error;
- void setError(QFile::FileError err);
- void setError(QFile::FileError err, const QString &errorString);
- void setError(QFile::FileError err, int errNum);
-
- mutable qint64 cachedSize;
private:
static QFile::EncoderFn encoder;
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
new file mode 100644
index 0000000000..17eedb0bdd
--- /dev/null
+++ b/src/corelib/io/qfiledevice.cpp
@@ -0,0 +1,736 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qfiledevice.h"
+#include "qfiledevice_p.h"
+#include "qfsfileengine_p.h"
+
+#ifdef QT_NO_QOBJECT
+#define tr(X) QString::fromLatin1(X)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const int QFILE_WRITEBUFFER_SIZE = 16384;
+
+QFileDevicePrivate::QFileDevicePrivate()
+ : fileEngine(0), lastWasWrite(false),
+ writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
+ cachedSize(0)
+{
+}
+
+QFileDevicePrivate::~QFileDevicePrivate()
+{
+ delete fileEngine;
+ fileEngine = 0;
+}
+
+QAbstractFileEngine * QFileDevicePrivate::engine() const
+{
+ if (!fileEngine)
+ fileEngine = new QFSFileEngine;
+ return fileEngine;
+}
+
+void QFileDevicePrivate::setError(QFileDevice::FileError err)
+{
+ error = err;
+ errorString.clear();
+}
+
+void QFileDevicePrivate::setError(QFileDevice::FileError err, const QString &errStr)
+{
+ error = err;
+ errorString = errStr;
+}
+
+void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum)
+{
+ error = err;
+ errorString = qt_error_string(errNum);
+}
+
+/*!
+ \enum QFileDevice::FileError
+
+ This enum describes the errors that may be returned by the error()
+ function.
+
+ \value NoError No error occurred.
+ \value ReadError An error occurred when reading from the file.
+ \value WriteError An error occurred when writing to the file.
+ \value FatalError A fatal error occurred.
+ \value ResourceError
+ \value OpenError The file could not be opened.
+ \value AbortError The operation was aborted.
+ \value TimeOutError A timeout occurred.
+ \value UnspecifiedError An unspecified error occurred.
+ \value RemoveError The file could not be removed.
+ \value RenameError The file could not be renamed.
+ \value PositionError The position in the file could not be changed.
+ \value ResizeError The file could not be resized.
+ \value PermissionsError The file could not be accessed.
+ \value CopyError The file could not be copied.
+
+ \omitvalue ConnectError
+*/
+
+/*!
+ \enum QFileDevice::Permission
+
+ This enum is used by the permission() function to report the
+ permissions and ownership of a file. The values may be OR-ed
+ together to test multiple permissions and ownership values.
+
+ \value ReadOwner The file is readable by the owner of the file.
+ \value WriteOwner The file is writable by the owner of the file.
+ \value ExeOwner The file is executable by the owner of the file.
+ \value ReadUser The file is readable by the user.
+ \value WriteUser The file is writable by the user.
+ \value ExeUser The file is executable by the user.
+ \value ReadGroup The file is readable by the group.
+ \value WriteGroup The file is writable by the group.
+ \value ExeGroup The file is executable by the group.
+ \value ReadOther The file is readable by anyone.
+ \value WriteOther The file is writable by anyone.
+ \value ExeOther The file is executable by anyone.
+
+ \warning Because of differences in the platforms supported by Qt,
+ the semantics of ReadUser, WriteUser and ExeUser are
+ platform-dependent: On Unix, the rights of the owner of the file
+ are returned and on Windows the rights of the current user are
+ returned. This behavior might change in a future Qt version.
+
+ Note that Qt does not by default check for permissions on NTFS
+ file systems, as this may decrease the performance of file
+ handling considerably. It is possible to force permission checking
+ on NTFS by including the following code in your source:
+
+ \snippet doc/src/snippets/ntfsp.cpp 0
+
+ Permission checking is then turned on and off by incrementing and
+ decrementing \c qt_ntfs_permission_lookup by 1.
+
+ \snippet doc/src/snippets/ntfsp.cpp 1
+*/
+
+//************* QFileDevice
+
+/*!
+ \class QFileDevice
+ \since 5.0
+
+ \brief The QFileDevice class provides an interface for reading from and writing to open files.
+
+ \ingroup io
+
+ \reentrant
+
+ QFileDevice is the base class for I/O devices that can read and write text and binary files
+ and \l{The Qt Resource System}{resources}. QFile offers the main functionality,
+ QFileDevice serves as a base class for sharing functionality with other file devices such
+ as QTemporaryFile, by providing all the operations that can be done on files that have
+ been opened by QFile or QTemporaryFile.
+
+ \sa QFile, QTemporaryFile
+*/
+
+/*!
+ \enum QFileDevice::FileHandleFlag
+
+ This enum is used when opening a file to specify additional
+ options which only apply to files and not to a generic
+ QIODevice.
+
+ \value AutoCloseHandle The file handle passed into open() should be
+ closed by close(), the default behavior is that close just flushes
+ the file and the application is responsible for closing the file handle.
+ When opening a file by name, this flag is ignored as Qt always owns the
+ file handle and must close it.
+ \value DontCloseHandle If not explicitly closed, the underlying file
+ handle is left open when the QFile object is destroyed.
+ */
+
+#ifdef QT_NO_QOBJECT
+QFileDevice::QFileDevice()
+ : QIODevice(*new QFileDevicePrivate)
+{
+}
+QFileDevice::QFileDevice(QFileDevicePrivate &dd)
+ : QIODevice(dd)
+{
+}
+#else
+/*!
+ \internal
+*/
+QFileDevice::QFileDevice()
+ : QIODevice(*new QFileDevicePrivate, 0)
+{
+}
+/*!
+ \internal
+*/
+QFileDevice::QFileDevice(QObject *parent)
+ : QIODevice(*new QFileDevicePrivate, parent)
+{
+}
+/*!
+ \internal
+*/
+QFileDevice::QFileDevice(QFileDevicePrivate &dd, QObject *parent)
+ : QIODevice(dd, parent)
+{
+}
+#endif
+
+/*!
+ Destroys the file device, closing it if necessary.
+*/
+QFileDevice::~QFileDevice()
+{
+ close();
+}
+
+/*!
+ Returns true if the file can only be manipulated sequentially;
+ otherwise returns false.
+
+ Most files support random-access, but some special files may not.
+
+ \sa QIODevice::isSequential()
+*/
+bool QFileDevice::isSequential() const
+{
+ Q_D(const QFileDevice);
+ return d->fileEngine && d->fileEngine->isSequential();
+}
+
+/*!
+ Returns the file handle of the file.
+
+ This is a small positive integer, suitable for use with C library
+ functions such as fdopen() and fcntl(). On systems that use file
+ descriptors for sockets (i.e. Unix systems, but not Windows) the handle
+ can be used with QSocketNotifier as well.
+
+ If the file is not open, or there is an error, handle() returns -1.
+
+ This function is not supported on Windows CE.
+
+ \sa QSocketNotifier
+*/
+int QFileDevice::handle() const
+{
+ Q_D(const QFileDevice);
+ if (!isOpen() || !d->fileEngine)
+ return -1;
+
+ return d->fileEngine->handle();
+}
+
+/*!
+ Returns the name of the file.
+ The default implementation in QFileDevice returns QString().
+*/
+QString QFileDevice::fileName() const
+{
+ return QString();
+}
+
+static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
+{
+ qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize());
+ if (ret > 0)
+ buffer->free(ret);
+ return ret;
+}
+
+/*!
+ Flushes any buffered data to the file. Returns true if successful;
+ otherwise returns false.
+*/
+bool QFileDevice::flush()
+{
+ Q_D(QFileDevice);
+ if (!d->fileEngine) {
+ qWarning("QFileDevice::flush: No file engine. Is IODevice open?");
+ return false;
+ }
+
+ if (!d->writeBuffer.isEmpty()) {
+ qint64 size = d->writeBuffer.size();
+ if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) {
+ QFileDevice::FileError err = d->fileEngine->error();
+ if (err == QFileDevice::UnspecifiedError)
+ err = QFileDevice::WriteError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+ }
+ }
+
+ if (!d->fileEngine->flush()) {
+ QFileDevice::FileError err = d->fileEngine->error();
+ if (err == QFileDevice::UnspecifiedError)
+ err = QFileDevice::WriteError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Calls QFileDevice::flush() and closes the file. Errors from flush are ignored.
+
+ \sa QIODevice::close()
+*/
+void QFileDevice::close()
+{
+ Q_D(QFileDevice);
+ if (!isOpen())
+ return;
+ bool flushed = flush();
+ QIODevice::close();
+
+ // reset write buffer
+ d->lastWasWrite = false;
+ d->writeBuffer.clear();
+
+ // keep earlier error from flush
+ if (d->fileEngine->close() && flushed)
+ unsetError();
+ else if (flushed)
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+}
+
+/*!
+ \reimp
+*/
+qint64 QFileDevice::pos() const
+{
+ return QIODevice::pos();
+}
+
+/*!
+ Returns true if the end of the file has been reached; otherwise returns
+ false.
+
+ For regular empty files on Unix (e.g. those in \c /proc), this function
+ returns true, since the file system reports that the size of such a file is
+ 0. Therefore, you should not depend on atEnd() when reading data from such a
+ file, but rather call read() until no more data can be read.
+*/
+bool QFileDevice::atEnd() const
+{
+ Q_D(const QFileDevice);
+
+ // If there's buffered data left, we're not at the end.
+ if (!d->buffer.isEmpty())
+ return false;
+
+ if (!isOpen())
+ return true;
+
+ if (!d->ensureFlushed())
+ return false;
+
+ // If the file engine knows best, say what it says.
+ if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
+ // Check if the file engine supports AtEndExtension, and if it does,
+ // check if the file engine claims to be at the end.
+ return d->fileEngine->atEnd();
+ }
+
+ // if it looks like we are at the end, or if size is not cached,
+ // fall through to bytesAvailable() to make sure.
+ if (pos() < d->cachedSize)
+ return false;
+
+ // Fall back to checking how much is available (will stat files).
+ return bytesAvailable() == 0;
+}
+
+/*!
+ \fn bool QFileDevice::seek(qint64 pos)
+
+ For random-access devices, this function sets the current position
+ to \a pos, returning true on success, or false if an error occurred.
+ For sequential devices, the default behavior is to do nothing and
+ return false.
+
+ Seeking beyond the end of a file:
+ If the position is beyond the end of a file, then seek() shall not
+ immediately extend the file. If a write is performed at this position,
+ then the file shall be extended. The content of the file between the
+ previous end of file and the newly written data is UNDEFINED and
+ varies between platforms and file systems.
+*/
+bool QFileDevice::seek(qint64 off)
+{
+ Q_D(QFileDevice);
+ if (!isOpen()) {
+ qWarning("QFileDevice::seek: IODevice is not open");
+ return false;
+ }
+
+ if (!d->ensureFlushed())
+ return false;
+
+ if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
+ QFileDevice::FileError err = d->fileEngine->error();
+ if (err == QFileDevice::UnspecifiedError)
+ err = QFileDevice::PositionError;
+ d->setError(err, d->fileEngine->errorString());
+ return false;
+ }
+ unsetError();
+ return true;
+}
+
+/*!
+ \reimp
+*/
+qint64 QFileDevice::readLineData(char *data, qint64 maxlen)
+{
+ Q_D(QFileDevice);
+ if (!d->ensureFlushed())
+ return -1;
+
+ qint64 read;
+ if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
+ read = d->fileEngine->readLine(data, maxlen);
+ } else {
+ // Fall back to QIODevice's readLine implementation if the engine
+ // cannot do it faster.
+ read = QIODevice::readLineData(data, maxlen);
+ }
+
+ if (read < maxlen) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
+
+ return read;
+}
+
+/*!
+ \reimp
+*/
+qint64 QFileDevice::readData(char *data, qint64 len)
+{
+ Q_D(QFileDevice);
+ unsetError();
+ if (!d->ensureFlushed())
+ return -1;
+
+ const qint64 read = d->fileEngine->read(data, len);
+ if (read < 0) {
+ QFileDevice::FileError err = d->fileEngine->error();
+ if (err == QFileDevice::UnspecifiedError)
+ err = QFileDevice::ReadError;
+ d->setError(err, d->fileEngine->errorString());
+ }
+
+ if (read < len) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
+
+ return read;
+}
+
+/*!
+ \internal
+*/
+bool QFileDevicePrivate::putCharHelper(char c)
+{
+#ifdef QT_NO_QOBJECT
+ return QIODevicePrivate::putCharHelper(c);
+#else
+
+ // Cutoff for code that doesn't only touch the buffer.
+ int writeBufferSize = writeBuffer.size();
+ if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
+#ifdef Q_OS_WIN
+ || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
+#endif
+ ) {
+ return QIODevicePrivate::putCharHelper(c);
+ }
+
+ if (!(openMode & QIODevice::WriteOnly)) {
+ if (openMode == QIODevice::NotOpen)
+ qWarning("QIODevice::putChar: Closed device");
+ else
+ qWarning("QIODevice::putChar: ReadOnly device");
+ return false;
+ }
+
+ // Make sure the device is positioned correctly.
+ const bool sequential = isSequential();
+ if (pos != devicePos && !sequential && !q_func()->seek(pos))
+ return false;
+
+ lastWasWrite = true;
+
+ int len = 1;
+#ifdef Q_OS_WIN
+ if ((openMode & QIODevice::Text) && c == '\n') {
+ ++len;
+ *writeBuffer.reserve(1) = '\r';
+ }
+#endif
+
+ // Write to buffer.
+ *writeBuffer.reserve(1) = c;
+
+ if (!sequential) {
+ pos += len;
+ devicePos += len;
+ if (!buffer.isEmpty())
+ buffer.skip(len);
+ }
+
+ return true;
+#endif
+}
+
+/*!
+ \reimp
+*/
+qint64 QFileDevice::writeData(const char *data, qint64 len)
+{
+ Q_D(QFileDevice);
+ unsetError();
+ d->lastWasWrite = true;
+ bool buffered = !(d->openMode & Unbuffered);
+
+ // Flush buffered data if this read will overflow.
+ if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
+ if (!flush())
+ return -1;
+ }
+
+ // Write directly to the engine if the block size is larger than
+ // the write buffer size.
+ if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
+ const qint64 ret = d->fileEngine->write(data, len);
+ if (ret < 0) {
+ QFileDevice::FileError err = d->fileEngine->error();
+ if (err == QFileDevice::UnspecifiedError)
+ err = QFileDevice::WriteError;
+ d->setError(err, d->fileEngine->errorString());
+ }
+ return ret;
+ }
+
+ // Write to the buffer.
+ char *writePointer = d->writeBuffer.reserve(len);
+ if (len == 1)
+ *writePointer = *data;
+ else
+ ::memcpy(writePointer, data, len);
+ return len;
+}
+
+/*!
+ Returns the file error status.
+
+ The I/O device status returns an error code. For example, if open()
+ returns false, or a read/write operation returns -1, this function can
+ be called to find out the reason why the operation failed.
+
+ \sa unsetError()
+*/
+QFileDevice::FileError QFileDevice::error() const
+{
+ Q_D(const QFileDevice);
+ return d->error;
+}
+
+/*!
+ Sets the file's error to QFileDevice::NoError.
+
+ \sa error()
+*/
+void QFileDevice::unsetError()
+{
+ Q_D(QFileDevice);
+ d->setError(QFileDevice::NoError);
+}
+
+/*!
+ Returns the size of the file.
+
+ For regular empty files on Unix (e.g. those in \c /proc), this function
+ returns 0; the contents of such a file are generated on demand in response
+ to you calling read().
+*/
+qint64 QFileDevice::size() const
+{
+ Q_D(const QFileDevice);
+ if (!d->ensureFlushed())
+ return 0;
+ d->cachedSize = d->engine()->size();
+ return d->cachedSize;
+}
+
+/*!
+ Sets the file size (in bytes) \a sz. Returns true if the file if the
+ resize succeeds; false otherwise. If \a sz is larger than the file
+ currently is the new bytes will be set to 0, if \a sz is smaller the
+ file is simply truncated.
+
+ \sa size()
+*/
+bool QFileDevice::resize(qint64 sz)
+{
+ Q_D(QFileDevice);
+ if (!d->ensureFlushed())
+ return false;
+ d->engine();
+ if (isOpen() && d->fileEngine->pos() > sz)
+ seek(sz);
+ if (d->fileEngine->setSize(sz)) {
+ unsetError();
+ d->cachedSize = sz;
+ return true;
+ }
+ d->cachedSize = 0;
+ d->setError(QFile::ResizeError, d->fileEngine->errorString());
+ return false;
+}
+
+/*!
+ Returns the complete OR-ed together combination of
+ QFile::Permission for the file.
+
+ \sa setPermissions()
+*/
+QFile::Permissions QFileDevice::permissions() const
+{
+ Q_D(const QFileDevice);
+ QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
+ return QFile::Permissions((int)perms); //ewww
+}
+
+/*!
+ Sets the permissions for the file to the \a permissions specified.
+ Returns true if successful, or false if the permissions cannot be
+ modified.
+
+ \sa permissions()
+*/
+bool QFileDevice::setPermissions(Permissions permissions)
+{
+ Q_D(QFileDevice);
+ if (d->engine()->setPermissions(permissions)) {
+ unsetError();
+ return true;
+ }
+ d->setError(QFile::PermissionsError, d->fileEngine->errorString());
+ return false;
+}
+
+/*!
+ \enum QFileDevice::MemoryMapFlags
+ \since 4.4
+
+ This enum describes special options that may be used by the map()
+ function.
+
+ \value NoOptions No options.
+*/
+
+/*!
+ Maps \a size bytes of the file into memory starting at \a offset. A file
+ should be open for a map to succeed but the file does not need to stay
+ open after the memory has been mapped. When the QFile is destroyed
+ or a new file is opened with this object, any maps that have not been
+ unmapped will automatically be unmapped.
+
+ Any mapping options can be passed through \a flags.
+
+ Returns a pointer to the memory or 0 if there is an error.
+
+ \note On Windows CE 5.0 the file will be closed before mapping occurs.
+
+ \sa unmap()
+ */
+uchar *QFileDevice::map(qint64 offset, qint64 size, MemoryMapFlags flags)
+{
+ Q_D(QFileDevice);
+ if (d->engine()
+ && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
+ unsetError();
+ uchar *address = d->fileEngine->map(offset, size, flags);
+ if (address == 0)
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+ return address;
+ }
+ return 0;
+}
+
+/*!
+ Unmaps the memory \a address.
+
+ Returns true if the unmap succeeds; false otherwise.
+
+ \sa map()
+ */
+bool QFileDevice::unmap(uchar *address)
+{
+ Q_D(QFileDevice);
+ if (d->engine()
+ && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
+ unsetError();
+ bool success = d->fileEngine->unmap(address);
+ if (!success)
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+ return success;
+ }
+ d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
new file mode 100644
index 0000000000..bbde91842c
--- /dev/null
+++ b/src/corelib/io/qfiledevice.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEDEVICE_H
+#define QFILEDEVICE_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QFileDevicePrivate;
+
+class Q_CORE_EXPORT QFileDevice : public QIODevice
+{
+#ifndef QT_NO_QOBJECT
+ Q_OBJECT
+#endif
+ Q_DECLARE_PRIVATE(QFileDevice)
+
+public:
+ enum FileError {
+ NoError = 0,
+ ReadError = 1,
+ WriteError = 2,
+ FatalError = 3,
+ ResourceError = 4,
+ OpenError = 5,
+ AbortError = 6,
+ TimeOutError = 7,
+ UnspecifiedError = 8,
+ RemoveError = 9,
+ RenameError = 10,
+ PositionError = 11,
+ ResizeError = 12,
+ PermissionsError = 13,
+ CopyError = 14
+ };
+
+ enum Permission {
+ ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000,
+ ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100,
+ ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010,
+ ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001
+ };
+ Q_DECLARE_FLAGS(Permissions, Permission)
+
+ enum FileHandleFlag {
+ AutoCloseHandle = 0x0001,
+ DontCloseHandle = 0
+ };
+ Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag)
+
+ ~QFileDevice();
+
+ FileError error() const;
+ void unsetError();
+
+ virtual void close();
+
+ bool isSequential() const;
+
+ int handle() const;
+ virtual QString fileName() const;
+
+ qint64 pos() const;
+ bool seek(qint64 offset);
+ bool atEnd() const;
+ bool flush();
+
+ qint64 size() const;
+
+ virtual bool resize(qint64 sz);
+ virtual Permissions permissions() const;
+ virtual bool setPermissions(Permissions permissionSpec);
+
+ enum MemoryMapFlags {
+ NoOptions = 0
+ };
+
+ uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
+ bool unmap(uchar *address);
+
+protected:
+ QFileDevice();
+#ifdef QT_NO_QOBJECT
+ QFileDevice(QFileDevicePrivate &dd);
+#else
+ explicit QFileDevice(QObject *parent);
+ QFileDevice(QFileDevicePrivate &dd, QObject *parent = 0);
+#endif
+
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+ qint64 readLineData(char *data, qint64 maxlen);
+
+private:
+ Q_DISABLE_COPY(QFileDevice)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::Permissions)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFILEDEVICE_H
diff --git a/src/corelib/io/qfiledevice_p.h b/src/corelib/io/qfiledevice_p.h
new file mode 100644
index 0000000000..2550cd73a2
--- /dev/null
+++ b/src/corelib/io/qfiledevice_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEDEVICE_P_H
+#define QFILEDEVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qiodevice_p.h"
+#include "private/qringbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractFileEngine;
+class QFSFileEngine;
+
+class QFileDevicePrivate : public QIODevicePrivate
+{
+ Q_DECLARE_PUBLIC(QFileDevice)
+protected:
+ QFileDevicePrivate();
+ ~QFileDevicePrivate();
+
+ virtual QAbstractFileEngine *engine() const;
+
+ QFileDevice::FileHandleFlags handleFlags;
+
+ mutable QAbstractFileEngine *fileEngine;
+ bool lastWasWrite;
+ QRingBuffer writeBuffer;
+ inline bool ensureFlushed() const;
+
+ bool putCharHelper(char c);
+
+ QFileDevice::FileError error;
+ void setError(QFileDevice::FileError err);
+ void setError(QFileDevice::FileError err, const QString &errorString);
+ void setError(QFileDevice::FileError err, int errNum);
+
+ mutable qint64 cachedSize;
+};
+
+inline bool QFileDevicePrivate::ensureFlushed() const
+{
+ // This function ensures that the write buffer has been flushed (const
+ // because certain const functions need to call it.
+ if (lastWasWrite) {
+ const_cast<QFileDevicePrivate *>(this)->lastWasWrite = false;
+ if (!const_cast<QFileDevice *>(q_func())->flush())
+ return false;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QFILEDEVICE_P_H
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index cb703df8c6..0411b463b3 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -696,7 +696,7 @@ void QTextStreamPrivate::flushWriteBuffer()
// flush the file
#ifndef QT_NO_QOBJECT
- QFile *file = qobject_cast<QFile *>(device);
+ QFileDevice *file = qobject_cast<QFileDevice *>(device);
bool flushed = !file || file->flush();
#else
bool flushed = true;
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 0659053937..9b15c1fd98 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -170,6 +170,8 @@
\value RemoveQuery The query part of the URL (following a '?' character)
is removed.
\value RemoveFragment
+ \value PreferLocalFile If the URL is a local file according to isLocalFile()
+ and contains no query or fragment, a local file path is returned.
\value StripTrailingSlash The trailing slash is removed if one is present.
Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
@@ -331,6 +333,7 @@ public:
void clear();
QByteArray toEncoded(QUrl::FormattingOptions options = QUrl::None) const;
+ bool isLocalFile() const;
QAtomicInt ref;
@@ -3953,6 +3956,9 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const
if (options==0x100) // private - see qHash(QUrl)
return normalized();
+ if ((options & QUrl::PreferLocalFile) && isLocalFile() && !hasQuery && !hasFragment)
+ return encodedPath;
+
QByteArray url;
if (!(options & QUrl::RemoveScheme) && !scheme.isEmpty()) {
@@ -5695,9 +5701,12 @@ QString QUrl::toString(FormattingOptions options) const
QString url;
+ const QString ourPath = path();
+ if ((options & QUrl::PreferLocalFile) && isLocalFile() && !d->hasQuery && !d->hasFragment)
+ return ourPath;
+
if (!(options & QUrl::RemoveScheme) && !d->scheme.isEmpty())
url += d->scheme + QLatin1Char(':');
- QString ourPath = path();
if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority) {
bool doFileScheme = d->scheme == QLatin1String("file") && ourPath.startsWith(QLatin1Char('/'));
QString tmp = d->authority(options);
@@ -5733,6 +5742,7 @@ QString QUrl::toString(FormattingOptions options) const
}
/*!
+ \since 5.0
Returns a string representation of the URL.
The output can be customized by passing flags with \a options.
@@ -5748,13 +5758,16 @@ QString QUrl::url(FormattingOptions options) const
}
/*!
+ \since 5.0
+
Returns a human-displayable string representation of the URL.
The output can be customized by passing flags with \a options.
The option RemovePassword is always enabled, since passwords
should never be shown back to users.
- The resulting QString can be passed back to a QUrl later on,
- but any password that was present initially will be lost.
+ With the default options, the resulting QString can be passed back
+ to a QUrl later on, but any password that was present initially will
+ be lost.
\sa FormattingOptions, toEncoded(), toString()
*/
@@ -6171,6 +6184,13 @@ QString QUrl::toLocalFile() const
return tmp;
}
+bool QUrlPrivate::isLocalFile() const
+{
+ if (scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0)
+ return false; // not file
+ return true;
+}
+
/*!
\since 4.7
Returns true if this URL is pointing to a local file path. A URL is a
@@ -6186,10 +6206,7 @@ bool QUrl::isLocalFile() const
{
if (!d) return false;
if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse();
-
- if (d->scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0)
- return false; // not file
- return true;
+ return d->isLocalFile();
}
/*!
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 3e5c62cd7c..fc49231594 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -76,6 +76,7 @@ public:
RemoveQuery = 0x40,
RemoveFragment = 0x80,
// 0x100: private: normalized
+ PreferLocalFile = 0x200,
StripTrailingSlash = 0x10000
};
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index 3c82199038..d80fcb683c 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -59,7 +59,7 @@ class Q_CORE_EXPORT QAbstractProxyModel : public QAbstractItemModel
Q_OBJECT
public:
- QAbstractProxyModel(QObject *parent = 0);
+ explicit QAbstractProxyModel(QObject *parent = 0);
~QAbstractProxyModel();
virtual void setSourceModel(QAbstractItemModel *sourceModel);
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index 8c7433d307..f18b1fccb1 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -73,7 +73,7 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole)
public:
- QSortFilterProxyModel(QObject *parent = 0);
+ explicit QSortFilterProxyModel(QObject *parent = 0);
~QSortFilterProxyModel();
void setSourceModel(QAbstractItemModel *sourceModel);
diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h
index d8b3f87f4a..a6bc4e7bd3 100644
--- a/src/corelib/itemmodels/qstringlistmodel.h
+++ b/src/corelib/itemmodels/qstringlistmodel.h
@@ -57,7 +57,7 @@ class Q_CORE_EXPORT QStringListModel : public QAbstractListModel
Q_OBJECT
public:
explicit QStringListModel(QObject *parent = 0);
- QStringListModel(const QStringList &strings, QObject *parent = 0);
+ explicit QStringListModel(const QStringList &strings, QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp
index b4a689da60..2eedef67ce 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/json/qjsonvalue.cpp
@@ -400,7 +400,7 @@ QString QJsonValue::toString() const
if (t != String)
return QString();
stringData->ref.ref(); // the constructor below doesn't add a ref.
- return QString(*(const QConstStringData<1> *)stringData);
+ return QString(*(const QStaticStringData<1> *)stringData);
}
/*!
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 428c2629ff..185314520b 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -146,6 +146,90 @@ QT_BEGIN_NAMESPACE
static inline const QMetaObjectPrivate *priv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+static inline const QByteArrayData &stringData(const QMetaObject *mo, int index)
+{
+ Q_ASSERT(priv(mo->d.data)->revision >= 7);
+ const QByteArrayData &data = mo->d.stringdata[index];
+ Q_ASSERT(data.ref.isStatic());
+ Q_ASSERT(data.alloc == 0);
+ Q_ASSERT(data.capacityReserved == 0);
+ Q_ASSERT(data.size >= 0);
+ return data;
+}
+
+static inline QByteArray toByteArray(const QByteArrayData &d)
+{
+ return QByteArray(reinterpret_cast<const QStaticByteArrayData<0> &>(d));
+}
+
+static inline const char *legacyString(const QMetaObject *mo, int index)
+{
+ Q_ASSERT(priv(mo->d.data)->revision <= 6);
+ return reinterpret_cast<const char *>(mo->d.stringdata) + index;
+}
+
+static inline const char *rawStringData(const QMetaObject *mo, int index)
+{
+ if (priv(mo->d.data)->revision >= 7)
+ return stringData(mo, index).data();
+ else
+ return legacyString(mo, index);
+}
+
+static inline int stringSize(const QMetaObject *mo, int index)
+{
+ if (priv(mo->d.data)->revision >= 7)
+ return stringData(mo, index).size;
+ else
+ return qstrlen(legacyString(mo, index));
+}
+
+static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
+{
+ if (typeInfo & IsUnresolvedType) {
+ return toByteArray(stringData(mo, typeInfo & TypeNameIndexMask));
+ } else {
+ // ### Use the QMetaType::typeName() that returns QByteArray
+ const char *t = QMetaType::typeName(typeInfo);
+ return QByteArray::fromRawData(t, qstrlen(t));
+ }
+}
+
+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(toByteArray(stringData(mo, typeInfo & TypeNameIndexMask)));
+}
+
+class QMetaMethodPrivate : public QMetaMethod
+{
+public:
+ static const QMetaMethodPrivate *get(const QMetaMethod *q)
+ { return static_cast<const QMetaMethodPrivate *>(q); }
+
+ inline QByteArray signature() const;
+ inline QByteArray name() const;
+ inline int typesDataIndex() const;
+ inline const char *rawReturnTypeName() const;
+ inline int returnType() const;
+ inline int parameterCount() const;
+ inline int parametersDataIndex() const;
+ inline uint parameterTypeInfo(int index) const;
+ inline int parameterType(int index) const;
+ inline void getParameterTypes(int *types) const;
+ inline QList<QByteArray> parameterTypes() const;
+ inline QList<QByteArray> parameterNames() const;
+ inline QByteArray tag() const;
+
+private:
+ QMetaMethodPrivate();
+};
/*!
\since 4.5
@@ -249,12 +333,14 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
}
/*!
- \fn const char *QMetaObject::className() const
-
Returns the class name.
\sa superClass()
*/
+const char *QMetaObject::className() const
+{
+ return rawStringData(this, 0);
+}
/*!
\fn QMetaObject *QMetaObject::superClass() const
@@ -307,7 +393,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const
*/
QString QMetaObject::tr(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::DefaultCodec, n);
+ return QCoreApplication::translate(rawStringData(this, 0), s, c, QCoreApplication::DefaultCodec, n);
}
/*!
@@ -315,7 +401,7 @@ QString QMetaObject::tr(const char *s, const char *c, int n) const
*/
QString QMetaObject::trUtf8(const char *s, const char *c, int n) const
{
- return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8, n);
+ return QCoreApplication::translate(rawStringData(this, 0), s, c, QCoreApplication::UnicodeUTF8, n);
}
#endif // QT_NO_TRANSLATION
@@ -495,7 +581,37 @@ int QMetaObject::classInfoCount() const
return n;
}
+// Returns true if the method defined by the given meta-object&handle
+// matches the given name, argument count and argument types, otherwise
+// returns false.
+static bool methodMatch(const QMetaObject *m, int handle,
+ const QByteArray &name, int argc,
+ const QArgumentType *types)
+{
+ Q_ASSERT(priv(m->d.data)->revision >= 7);
+ if (int(m->d.data[handle + 1]) != argc)
+ return false;
+
+ if (toByteArray(stringData(m, m->d.data[handle])) != name)
+ return false;
+
+ int paramsIndex = m->d.data[handle + 2] + 1;
+ for (int i = 0; i < argc; ++i) {
+ uint typeInfo = m->d.data[paramsIndex + i];
+ if (types[i].type()) {
+ if (types[i].type() != typeFromTypeInfo(m, typeInfo))
+ return false;
+ } else {
+ if (types[i].name() != typeNameFromTypeInfo(m, typeInfo))
+ return false;
+ }
+ }
+
+ return true;
+}
+
/** \internal
+* \obsolete
* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
* the baseObject
* \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
@@ -506,6 +622,8 @@ static inline int indexOfMethodRelative(const QMetaObject **baseObject,
const char *method,
bool normalizeStringData)
{
+ QByteArray methodName;
+ QArgumentTypeArray methodArgumentTypes;
for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4)
? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
@@ -513,15 +631,26 @@ static inline int indexOfMethodRelative(const QMetaObject **baseObject,
? (priv(m->d.data)->signalCount) : 0;
if (!normalizeStringData) {
for (; i >= end; --i) {
- const char *stringdata = m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i];
- if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) {
- *baseObject = m;
- return i;
+ if (priv(m->d.data)->revision >= 7) {
+ if (methodName.isEmpty())
+ methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodArgumentTypes);
+ int handle = priv(m->d.data)->methodData + 5*i;
+ if (methodMatch(m, handle, methodName, methodArgumentTypes.size(),
+ methodArgumentTypes.constData())) {
+ *baseObject = m;
+ return i;
+ }
+ } else {
+ const char *stringdata = legacyString(m, m->d.data[priv(m->d.data)->methodData + 5*i]);
+ if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) {
+ *baseObject = m;
+ return i;
+ }
}
}
} else if (priv(m->d.data)->revision < 5) {
for (; i >= end; --i) {
- const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]);
+ const char *stringdata = legacyString(m, m->d.data[priv(m->d.data)->methodData + 5 * i]);
const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata);
if (normalizedSignature == method) {
*baseObject = m;
@@ -533,6 +662,34 @@ static inline int indexOfMethodRelative(const QMetaObject **baseObject,
return -1;
}
+/** \internal
+* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
+* the baseObject
+* \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
+*/
+template<int MethodType>
+static inline int indexOfMethodRelative(const QMetaObject **baseObject,
+ const QByteArray &name, int argc,
+ const QArgumentType *types)
+{
+ for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
+ Q_ASSERT(priv(m->d.data)->revision >= 7);
+ int i = (MethodType == MethodSignal)
+ ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
+ const int end = (MethodType == MethodSlot)
+ ? (priv(m->d.data)->signalCount) : 0;
+
+ for (; i >= end; --i) {
+ int handle = priv(m->d.data)->methodData + 5*i;
+ if (methodMatch(m, handle, name, argc, types)) {
+ *baseObject = m;
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
/*!
\since 4.5
@@ -548,10 +705,16 @@ int QMetaObject::indexOfConstructor(const char *constructor) const
{
if (priv(d.data)->revision < 2)
return -1;
- for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) {
- const char *data = d.stringdata + d.data[priv(d.data)->constructorData + 5*i];
- if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) {
- return i;
+ else if (priv(d.data)->revision >= 7) {
+ QArgumentTypeArray types;
+ QByteArray name = QMetaObjectPrivate::decodeMethodSignature(constructor, types);
+ return QMetaObjectPrivate::indexOfConstructor(this, name, types.size(), types.constData());
+ } else {
+ for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) {
+ const char *data = legacyString(this, d.data[priv(d.data)->constructorData + 5*i]);
+ if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) {
+ return i;
+ }
}
}
return -1;
@@ -568,16 +731,60 @@ int QMetaObject::indexOfConstructor(const char *constructor) const
int QMetaObject::indexOfMethod(const char *method) const
{
const QMetaObject *m = this;
- int i = indexOfMethodRelative<0>(&m, method, false);
- if (i < 0) {
- m = this;
- i = indexOfMethodRelative<0>(&m, method, true);
+ int i;
+ if (priv(m->d.data)->revision >= 7) {
+ QArgumentTypeArray types;
+ QByteArray name = QMetaObjectPrivate::decodeMethodSignature(method, types);
+ i = indexOfMethodRelative<0>(&m, name, types.size(), types.constData());
+ } else {
+ i = indexOfMethodRelative<0>(&m, method, false);
+ if (i < 0) {
+ m = this;
+ i = indexOfMethodRelative<0>(&m, method, true);
+ }
}
if (i >= 0)
i += m->methodOffset();
return i;
}
+// Parses a string of comma-separated types into QArgumentTypes.
+static void argumentTypesFromString(const char *str, const char *end,
+ QArgumentTypeArray &types)
+{
+ Q_ASSERT(str <= end);
+ while (str != end) {
+ if (!types.isEmpty())
+ ++str; // Skip comma
+ const char *begin = str;
+ int level = 0;
+ while (str != end && (level > 0 || *str != ',')) {
+ if (*str == '<')
+ ++level;
+ else if (*str == '>')
+ --level;
+ ++str;
+ }
+ types += QArgumentType(QByteArray(begin, str - begin));
+ }
+}
+
+// Given a method \a signature (e.g. "foo(int,double)"), this function
+// populates the argument \a types array and returns the method name.
+QByteArray QMetaObjectPrivate::decodeMethodSignature(
+ const char *signature, QArgumentTypeArray &types)
+{
+ const char *lparens = strchr(signature, '(');
+ if (!lparens)
+ return QByteArray();
+ const char *rparens = strchr(lparens + 1, ')');
+ if (!rparens || *(rparens+1))
+ return QByteArray();
+ int nameLength = lparens - signature;
+ argumentTypesFromString(lparens + 1, rparens, types);
+ return QByteArray::fromRawData(signature, nameLength);
+}
+
/*!
Finds \a signal and returns its index; otherwise returns -1.
@@ -592,10 +799,17 @@ int QMetaObject::indexOfMethod(const char *method) const
int QMetaObject::indexOfSignal(const char *signal) const
{
const QMetaObject *m = this;
- int i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, false);
- if (i < 0) {
- m = this;
- i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, true);
+ int i;
+ if (priv(m->d.data)->revision >= 7) {
+ QArgumentTypeArray types;
+ QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signal, types);
+ i = QMetaObjectPrivate::indexOfSignalRelative(&m, name, types.size(), types.constData());
+ } else {
+ i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, false);
+ if (i < 0) {
+ m = this;
+ i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, true);
+ }
}
if (i >= 0)
i += m->methodOffset();
@@ -603,6 +817,7 @@ int QMetaObject::indexOfSignal(const char *signal) const
}
/*! \internal
+ \obsolete
Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
\a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
@@ -618,12 +833,37 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
int conflict = m->d.superdata->indexOfMethod(signal);
if (conflict >= 0)
qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
- signal, m->d.superdata->d.stringdata, m->d.stringdata);
+ signal, rawStringData(m->d.superdata, 0), rawStringData(m, 0));
}
#endif
return i;
}
+/*! \internal
+ Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
+
+ \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
+*/
+int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
+ const QByteArray &name, int argc,
+ const QArgumentType *types)
+{
+ int i = indexOfMethodRelative<MethodSignal>(baseObject, name, argc, types);
+#ifndef QT_NO_DEBUG
+ const QMetaObject *m = *baseObject;
+ if (i >= 0 && m && m->d.superdata) {
+ int conflict = indexOfMethod(m->d.superdata, name, argc, types);
+ if (conflict >= 0) {
+ QMetaMethod conflictMethod = m->d.superdata->method(conflict);
+ qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
+ conflictMethod.methodSignature().constData(),
+ rawStringData(m->d.superdata, 0), rawStringData(m, 0));
+ }
+ }
+ #endif
+ return i;
+}
+
/*!
Finds \a slot and returns its index; otherwise returns -1.
@@ -635,9 +875,16 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
int QMetaObject::indexOfSlot(const char *slot) const
{
const QMetaObject *m = this;
- int i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, false);
- if (i < 0)
- i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, true);
+ int i;
+ if (priv(m->d.data)->revision >= 7) {
+ QArgumentTypeArray types;
+ QByteArray name = QMetaObjectPrivate::decodeMethodSignature(slot, types);
+ i = QMetaObjectPrivate::indexOfSlotRelative(&m, name, types.size(), types.constData());
+ } else {
+ i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, false);
+ if (i < 0)
+ i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, true);
+ }
if (i >= 0)
i += m->methodOffset();
return i;
@@ -651,10 +898,108 @@ int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
return indexOfMethodRelative<MethodSlot>(m, slot, normalizeStringData);
}
+// same as indexOfSignalRelative but for slots.
+int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
+ const QByteArray &name, int argc,
+ const QArgumentType *types)
+{
+ return indexOfMethodRelative<MethodSlot>(m, name, argc, types);
+}
+
+int QMetaObjectPrivate::indexOfSignal(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types)
+{
+ int i = indexOfSignalRelative(&m, name, argc, types);
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+int QMetaObjectPrivate::indexOfSlot(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types)
+{
+ int i = indexOfSlotRelative(&m, name, argc, types);
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+int QMetaObjectPrivate::indexOfMethod(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types)
+{
+ int i = indexOfMethodRelative<0>(&m, name, argc, types);
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types)
+{
+ for (int i = priv(m->d.data)->constructorCount-1; i >= 0; --i) {
+ int handle = priv(m->d.data)->constructorData + 5*i;
+ if (methodMatch(m, handle, name, argc, types))
+ return i;
+ }
+ return -1;
+}
+
+/*!
+ \internal
+
+ Returns true if the \a signalTypes and \a methodTypes are
+ compatible; otherwise returns false.
+*/
+bool QMetaObjectPrivate::checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
+ int methodArgc, const QArgumentType *methodTypes)
+{
+ if (signalArgc < methodArgc)
+ return false;
+ for (int i = 0; i < methodArgc; ++i) {
+ if (signalTypes[i] != methodTypes[i])
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+
+ Returns true if the \a signal and \a method arguments are
+ compatible; otherwise returns false.
+*/
+bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
+ const QMetaMethodPrivate *method)
+{
+ if (signal->methodType() != QMetaMethod::Signal)
+ return false;
+ if (signal->parameterCount() < method->parameterCount())
+ return false;
+ const QMetaObject *smeta = signal->enclosingMetaObject();
+ const QMetaObject *rmeta = method->enclosingMetaObject();
+ for (int i = 0; i < method->parameterCount(); ++i) {
+ uint sourceTypeInfo = signal->parameterTypeInfo(i);
+ uint targetTypeInfo = method->parameterTypeInfo(i);
+ if ((sourceTypeInfo & IsUnresolvedType)
+ || (targetTypeInfo & IsUnresolvedType)) {
+ QByteArray sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
+ QByteArray targetName = typeNameFromTypeInfo(rmeta, targetTypeInfo);
+ if (sourceName != targetName)
+ return false;
+ } else {
+ int sourceType = typeFromTypeInfo(smeta, sourceTypeInfo);
+ int targetType = typeFromTypeInfo(rmeta, targetTypeInfo);
+ if (sourceType != targetType)
+ return false;
+ }
+ }
+ return true;
+}
+
static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
{
while (self) {
- if (strcmp(self->d.stringdata, name) == 0)
+ if (strcmp(rawStringData(self, 0), name) == 0)
return self;
if (self->d.extradata) {
const QMetaObject **e;
@@ -690,7 +1035,7 @@ int QMetaObject::indexOfEnumerator(const char *name) const
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
for (int i = d->enumeratorCount - 1; i >= 0; --i) {
- const char *prop = m->d.stringdata + m->d.data[d->enumeratorData + 4*i];
+ const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]);
if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
i += m->enumeratorOffset();
return i;
@@ -713,7 +1058,7 @@ int QMetaObject::indexOfProperty(const char *name) const
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
for (int i = d->propertyCount-1; i >= 0; --i) {
- const char *prop = m->d.stringdata + m->d.data[d->propertyData + 3*i];
+ const char *prop = rawStringData(m, m->d.data[d->propertyData + 3*i]);
if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
i += m->propertyOffset();
return i;
@@ -744,8 +1089,7 @@ int QMetaObject::indexOfClassInfo(const char *name) const
const QMetaObject *m = this;
while (m && i < 0) {
for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
- if (strcmp(name, m->d.stringdata
- + m->d.data[priv(m->d.data)->classInfoData + 2*i]) == 0) {
+ if (strcmp(name, rawStringData(m, m->d.data[priv(m->d.data)->classInfoData + 2*i])) == 0) {
i += m->classInfoOffset();
break;
}
@@ -829,16 +1173,20 @@ QMetaProperty QMetaObject::property(int index) const
if (i >= 0 && i < priv(d.data)->propertyCount) {
int handle = priv(d.data)->propertyData + 3*i;
int flags = d.data[handle + 2];
- const char *type = d.stringdata + d.data[handle + 1];
result.mobj = this;
result.handle = handle;
result.idx = i;
if (flags & EnumOrFlag) {
+ const char *type;
+ if (priv(d.data)->revision >= 7)
+ type = rawTypeNameFromTypeInfo(this, d.data[handle + 1]);
+ else
+ type = legacyString(this, d.data[handle + 1]);
result.menum = enumerator(indexOfEnumerator(type));
if (!result.menum.isValid()) {
const char *enum_name = type;
- const char *scope_name = d.stringdata;
+ const char *scope_name = rawStringData(this, 0);
char *scope_buffer = 0;
const char *colon = strrchr(enum_name, ':');
@@ -934,6 +1282,21 @@ bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
return false;
}
+/*!
+ \since 5.0
+ \overload
+
+ Returns true if the \a signal and \a method arguments are
+ compatible; otherwise returns false.
+*/
+bool QMetaObject::checkConnectArgs(const QMetaMethod &signal,
+ const QMetaMethod &method)
+{
+ return QMetaObjectPrivate::checkConnectArgs(
+ QMetaMethodPrivate::get(&signal),
+ QMetaMethodPrivate::get(&method));
+}
+
static void qRemoveWhitespace(const char *s, char *d)
{
char last = 0;
@@ -1230,7 +1593,7 @@ bool QMetaObject::invokeMethod(QObject *obj,
\ingroup objectmodel
- A QMetaMethod has a methodType(), a signature(), a list of
+ A QMetaMethod has a methodType(), a methodSignature(), a list of
parameterTypes() and parameterNames(), a return typeName(), a
tag(), and an access() specifier. You can use invoke() to invoke
the method on an arbitrary QObject.
@@ -1275,72 +1638,284 @@ bool QMetaObject::invokeMethod(QObject *obj,
\internal
*/
+QByteArray QMetaMethodPrivate::signature() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ QByteArray result;
+ result.reserve(256);
+ result += name();
+ result += '(';
+ QList<QByteArray> argTypes = parameterTypes();
+ for (int i = 0; i < argTypes.size(); ++i) {
+ if (i)
+ result += ',';
+ result += argTypes.at(i);
+ }
+ result += ')';
+ return result;
+}
+
+QByteArray QMetaMethodPrivate::name() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return toByteArray(stringData(mobj, mobj->d.data[handle]));
+}
+
+int QMetaMethodPrivate::typesDataIndex() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return mobj->d.data[handle + 2];
+}
+
+const char *QMetaMethodPrivate::rawReturnTypeName() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ uint typeInfo = mobj->d.data[typesDataIndex()];
+ if (typeInfo & IsUnresolvedType)
+ return rawStringData(mobj, typeInfo & TypeNameIndexMask);
+ else {
+ if (typeInfo == QMetaType::Void) {
+ // QMetaMethod::typeName() is documented to return an empty string
+ // if the return type is void, but QMetaType::typeName() returns
+ // "void".
+ return "";
+ }
+ return QMetaType::typeName(typeInfo);
+ }
+}
+
+int QMetaMethodPrivate::returnType() const
+{
+ return parameterType(-1);
+}
+
+int QMetaMethodPrivate::parameterCount() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return mobj->d.data[handle + 1];
+}
+
+int QMetaMethodPrivate::parametersDataIndex() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return typesDataIndex() + 1;
+}
+
+uint QMetaMethodPrivate::parameterTypeInfo(int index) const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return mobj->d.data[parametersDataIndex() + index];
+}
+
+int QMetaMethodPrivate::parameterType(int index) const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return typeFromTypeInfo(mobj, parameterTypeInfo(index));
+}
+
+void QMetaMethodPrivate::getParameterTypes(int *types) const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ int dataIndex = parametersDataIndex();
+ int argc = parameterCount();
+ for (int i = 0; i < argc; ++i) {
+ int id = typeFromTypeInfo(mobj, mobj->d.data[dataIndex++]);
+ *(types++) = id;
+ }
+}
+
+QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ QList<QByteArray> list;
+ int argc = parameterCount();
+ int paramsIndex = parametersDataIndex();
+ for (int i = 0; i < argc; ++i)
+ list += typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
+ return list;
+}
+
+QList<QByteArray> QMetaMethodPrivate::parameterNames() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ QList<QByteArray> list;
+ int argc = parameterCount();
+ int namesIndex = parametersDataIndex() + argc;
+ for (int i = 0; i < argc; ++i)
+ list += toByteArray(stringData(mobj, mobj->d.data[namesIndex + i]));
+ return list;
+}
+
+QByteArray QMetaMethodPrivate::tag() const
+{
+ Q_ASSERT(priv(mobj->d.data)->revision >= 7);
+ return toByteArray(stringData(mobj, mobj->d.data[handle + 3]));
+}
+
/*!
+ \since 5.0
+
Returns the signature of this method (e.g.,
\c{setValue(double)}).
\sa parameterTypes(), parameterNames()
*/
-const char *QMetaMethod::signature() const
+QByteArray QMetaMethod::methodSignature() const
+{
+ if (!mobj)
+ return QByteArray();
+ if (priv(mobj->d.data)->revision >= 7) {
+ return QMetaMethodPrivate::get(this)->signature();
+ } else {
+ const char *sig = rawStringData(mobj, mobj->d.data[handle]);
+ return QByteArray::fromRawData(sig, qstrlen(sig));
+ }
+}
+
+/*!
+ \since 5.0
+
+ Returns the name of this method.
+
+ \sa methodSignature(), parameterCount()
+*/
+QByteArray QMetaMethod::name() const
+{
+ if (!mobj)
+ return QByteArray();
+ return QMetaMethodPrivate::get(this)->name();
+}
+
+/*!
+ \since 5.0
+
+ Returns the return type of this method.
+
+ The return value is one of the types that are registered
+ with QMetaType, or QMetaType::UnknownType if the type is not registered.
+
+ \sa parameterType(), QMetaType, typeName()
+*/
+int QMetaMethod::returnType() const
+ {
+ if (!mobj)
+ return QMetaType::UnknownType;
+ return QMetaMethodPrivate::get(this)->returnType();
+}
+
+/*!
+ \since 5.0
+
+ Returns the number of parameters of this method.
+
+ \sa parameterType(), parameterNames()
+*/
+int QMetaMethod::parameterCount() const
{
if (!mobj)
return 0;
- return mobj->d.stringdata + mobj->d.data[handle];
+ return QMetaMethodPrivate::get(this)->parameterCount();
+}
+
+/*!
+ \since 5.0
+
+ Returns the type of the parameter at the given \a index.
+
+ The return value is one of the types that are registered
+ with QMetaType, or QMetaType::UnknownType if the type is not registered.
+
+ \sa parameterCount(), returnType(), QMetaType
+*/
+int QMetaMethod::parameterType(int index) const
+{
+ if (!mobj || index < 0)
+ return QMetaType::UnknownType;
+ if (index >= QMetaMethodPrivate::get(this)->parameterCount())
+ return QMetaType::UnknownType;
+ return QMetaMethodPrivate::get(this)->parameterType(index);
+}
+
+/*!
+ \since 5.0
+ \internal
+
+ Gets the parameter \a types of this method. The storage
+ for \a types must be able to hold parameterCount() items.
+
+ \sa parameterCount(), returnType(), parameterType()
+*/
+void QMetaMethod::getParameterTypes(int *types) const
+{
+ if (!mobj)
+ return;
+ QMetaMethodPrivate::get(this)->getParameterTypes(types);
}
/*!
Returns a list of parameter types.
- \sa parameterNames(), signature()
+ \sa parameterNames(), methodSignature()
*/
QList<QByteArray> QMetaMethod::parameterTypes() const
{
if (!mobj)
return QList<QByteArray>();
- return QMetaObjectPrivate::parameterTypeNamesFromSignature(
- mobj->d.stringdata + mobj->d.data[handle]);
+ if (priv(mobj->d.data)->revision >= 7) {
+ return QMetaMethodPrivate::get(this)->parameterTypes();
+ } else {
+ return QMetaObjectPrivate::parameterTypeNamesFromSignature(
+ legacyString(mobj, mobj->d.data[handle]));
+ }
}
/*!
Returns a list of parameter names.
- \sa parameterTypes(), signature()
+ \sa parameterTypes(), methodSignature()
*/
QList<QByteArray> QMetaMethod::parameterNames() const
{
QList<QByteArray> list;
if (!mobj)
return list;
- const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
- if (*names == 0) {
- // do we have one or zero arguments?
- const char *signature = mobj->d.stringdata + mobj->d.data[handle];
- while (*signature && *signature != '(')
- ++signature;
- if (*++signature != ')')
- list += QByteArray();
+ if (priv(mobj->d.data)->revision >= 7) {
+ return QMetaMethodPrivate::get(this)->parameterNames();
} else {
- --names;
- do {
- const char *begin = ++names;
- while (*names && *names != ',')
- ++names;
- list += QByteArray(begin, names - begin);
- } while (*names);
+ const char *names = rawStringData(mobj, mobj->d.data[handle + 1]);
+ if (*names == 0) {
+ // do we have one or zero arguments?
+ const char *signature = rawStringData(mobj, mobj->d.data[handle]);
+ while (*signature && *signature != '(')
+ ++signature;
+ if (*++signature != ')')
+ list += QByteArray();
+ } else {
+ --names;
+ do {
+ const char *begin = ++names;
+ while (*names && *names != ',')
+ ++names;
+ list += QByteArray(begin, names - begin);
+ } while (*names);
+ }
+ return list;
}
- return list;
}
/*!
- Returns the return type of this method, or an empty string if the
+ Returns the return type name of this method, or an empty string if the
return type is \e void.
*/
const char *QMetaMethod::typeName() const
{
if (!mobj)
return 0;
- return mobj->d.stringdata + mobj->d.data[handle + 2];
+ if (priv(mobj->d.data)->revision >= 7)
+ return QMetaMethodPrivate::get(this)->rawReturnTypeName();
+ else
+ return legacyString(mobj, mobj->d.data[handle + 2]);
}
/*!
@@ -1377,7 +1952,10 @@ const char *QMetaMethod::tag() const
{
if (!mobj)
return 0;
- return mobj->d.stringdata + mobj->d.data[handle + 3];
+ if (priv(mobj->d.data)->revision >= 7)
+ return QMetaMethodPrivate::get(this)->tag().constData();
+ else
+ return legacyString(mobj, mobj->d.data[handle + 3]);
}
@@ -1578,12 +2156,14 @@ bool QMetaMethod::invoke(QObject *object,
break;
}
int metaMethodArgumentCount = 0;
- {
+ if (priv(mobj->d.data)->revision >= 7) {
+ metaMethodArgumentCount = QMetaMethodPrivate::get(this)->parameterCount();
+ } else {
// based on QMetaObject::parameterNames()
- const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
+ const char *names = rawStringData(mobj, mobj->d.data[handle + 1]);
if (*names == 0) {
// do we have one or zero arguments?
- const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ const char *signature = rawStringData(mobj, mobj->d.data[handle]);
while (*signature && *signature != '(')
++signature;
if (*++signature != ')')
@@ -1661,7 +2241,7 @@ bool QMetaMethod::invoke(QObject *object,
for (int i = 1; i < paramCount; ++i) {
types[i] = QMetaType::type(typeNames[i]);
- if (types[i]) {
+ if (types[i] != QMetaType::UnknownType) {
args[i] = QMetaType::create(types[i], param[i]);
++nargs;
} else if (param[i]) {
@@ -1803,7 +2383,7 @@ const char *QMetaEnum::name() const
{
if (!mobj)
return 0;
- return mobj->d.stringdata + mobj->d.data[handle];
+ return rawStringData(mobj, mobj->d.data[handle]);
}
/*!
@@ -1831,7 +2411,7 @@ const char *QMetaEnum::key(int index) const
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
if (index >= 0 && index < count)
- return mobj->d.stringdata + mobj->d.data[data + 2*index];
+ return rawStringData(mobj, mobj->d.data[data + 2*index]);
return 0;
}
@@ -1878,7 +2458,7 @@ bool QMetaEnum::isFlag() const
*/
const char *QMetaEnum::scope() const
{
- return mobj?mobj->d.stringdata : 0;
+ return mobj?rawStringData(mobj, 0) : 0;
}
/*!
@@ -1910,8 +2490,8 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i) {
- if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key, mobj->d.stringdata, scope) == 0))
- && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) {
+ if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0))
+ && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
if (ok != 0)
*ok = true;
return mobj->d.data[data + 2*i + 1];
@@ -1936,7 +2516,7 @@ const char* QMetaEnum::valueToKey(int value) const
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i)
if (value == (int)mobj->d.data[data + 2*i + 1])
- return mobj->d.stringdata + mobj->d.data[data + 2*i];
+ return rawStringData(mobj, mobj->d.data[data + 2*i]);
return 0;
}
@@ -1979,8 +2559,8 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
}
int i;
for (i = count-1; i >= 0; --i)
- if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key.constData(), mobj->d.stringdata, scope) == 0))
- && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) {
+ if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0))
+ && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
value |= mobj->d.data[data + 2*i + 1];
break;
}
@@ -2013,7 +2593,10 @@ QByteArray QMetaEnum::valueToKeys(int value) const
v = v & ~k;
if (!keys.isEmpty())
keys += '|';
- keys += mobj->d.stringdata + mobj->d.data[data + 2*i];
+ if (priv(mobj->d.data)->revision >= 7)
+ keys += toByteArray(stringData(mobj, mobj->d.data[data + 2*i]));
+ else
+ keys += legacyString(mobj, mobj->d.data[data + 2*i]);
}
}
return keys;
@@ -2092,7 +2675,7 @@ const char *QMetaProperty::name() const
if (!mobj)
return 0;
int handle = priv(mobj->d.data)->propertyData + 3*idx;
- return mobj->d.stringdata + mobj->d.data[handle];
+ return rawStringData(mobj, mobj->d.data[handle]);
}
/*!
@@ -2105,7 +2688,10 @@ const char *QMetaProperty::typeName() const
if (!mobj)
return 0;
int handle = priv(mobj->d.data)->propertyData + 3*idx;
- return mobj->d.stringdata + mobj->d.data[handle + 1];
+ if (priv(mobj->d.data)->revision >= 7)
+ return rawTypeNameFromTypeInfo(mobj, mobj->d.data[handle + 1]);
+ else
+ return legacyString(mobj, mobj->d.data[handle + 1]);
}
/*!
@@ -2119,14 +2705,21 @@ QVariant::Type QMetaProperty::type() const
if (!mobj)
return QVariant::Invalid;
int handle = priv(mobj->d.data)->propertyData + 3*idx;
- uint flags = mobj->d.data[handle + 2];
- uint type = flags >> 24;
- if (type)
+ uint type;
+ if (priv(mobj->d.data)->revision >= 7) {
+ type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
+ if (type >= QMetaType::User)
+ return QVariant::UserType;
+ } else {
+ uint flags = mobj->d.data[handle + 2];
+ type = flags >> 24;
+ }
+ if (type != QMetaType::UnknownType)
return QVariant::Type(type);
if (isEnumType()) {
int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
- if (enumMetaTypeId == 0)
+ if (enumMetaTypeId == QMetaType::UnknownType)
return QVariant::Int;
}
#ifdef QT_COORD_TYPE
@@ -2142,18 +2735,29 @@ QVariant::Type QMetaProperty::type() const
\since 4.2
Returns this property's user type. The return value is one
- of the values that are registered with QMetaType, or 0 if
+ of the values that are registered with QMetaType, or QMetaType::UnknownType if
the type is not registered.
\sa type(), QMetaType, typeName()
*/
int QMetaProperty::userType() const
{
- QVariant::Type tp = type();
- if (tp != QVariant::UserType)
- return tp;
+ if (!mobj)
+ return QMetaType::UnknownType;
+ if (priv(mobj->d.data)->revision >= 7) {
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ int type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
+ if (type != QMetaType::UnknownType)
+ return type;
+ } else {
+ QVariant::Type tp = type();
+ if (tp != QVariant::UserType)
+ return tp;
+ }
if (isEnumType()) {
int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if (enumMetaTypeId == QMetaType::UnknownType)
+ return QVariant::Int; // Match behavior of QMetaType::type()
return enumMetaTypeId;
}
return QMetaType::type(typeName());
@@ -2249,18 +2853,30 @@ QVariant QMetaProperty::read(const QObject *object) const
with QMetaType)
*/
int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
- if (enumMetaTypeId != 0)
+ if (enumMetaTypeId != QMetaType::UnknownType)
t = enumMetaTypeId;
} else {
int handle = priv(mobj->d.data)->propertyData + 3*idx;
- uint flags = mobj->d.data[handle + 2];
- const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
- t = (flags >> 24);
- if (t == QVariant::Invalid)
- t = QMetaType::type(typeName);
- if (t == QVariant::Invalid)
- t = QVariant::nameToType(typeName);
- if (t == QVariant::Invalid) {
+ const char *typeName = 0;
+ if (priv(mobj->d.data)->revision >= 7) {
+ uint typeInfo = mobj->d.data[handle + 1];
+ if (!(typeInfo & IsUnresolvedType))
+ t = typeInfo;
+ else {
+ typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask);
+ t = QMetaType::type(typeName);
+ }
+ } else {
+ uint flags = mobj->d.data[handle + 2];
+ t = (flags >> 24);
+ if (t == QMetaType::UnknownType) {
+ typeName = legacyString(mobj, mobj->d.data[handle + 1]);
+ t = QMetaType::type(typeName);
+ if (t == QMetaType::UnknownType)
+ t = QVariant::nameToType(typeName);
+ }
+ }
+ if (t == QMetaType::UnknownType) {
qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
return QVariant();
}
@@ -2315,17 +2931,29 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
return false;
} else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
- if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
return false;
v = QVariant(*reinterpret_cast<const int *>(v.constData()));
}
v.convert(QVariant::Int);
} else {
int handle = priv(mobj->d.data)->propertyData + 3*idx;
- uint flags = mobj->d.data[handle + 2];
- t = flags >> 24;
- if (t == QVariant::Invalid) {
- const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
+ const char *typeName = 0;
+ if (priv(mobj->d.data)->revision >= 7) {
+ uint typeInfo = mobj->d.data[handle + 1];
+ if (!(typeInfo & IsUnresolvedType))
+ t = typeInfo;
+ else {
+ typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask);
+ t = QMetaType::type(typeName);
+ }
+ } else {
+ uint flags = mobj->d.data[handle + 2];
+ t = flags >> 24;
+ typeName = legacyString(mobj, mobj->d.data[handle + 1]);
+ }
+ if (t == QMetaType::UnknownType) {
+ const char *typeName = rawStringData(mobj, mobj->d.data[handle + 1]);
const char *vtypeName = value.typeName();
if (vtypeName && strcmp(typeName, vtypeName) == 0)
t = value.userType();
@@ -2691,7 +3319,7 @@ const char *QMetaClassInfo::name() const
{
if (!mobj)
return 0;
- return mobj->d.stringdata + mobj->d.data[handle];
+ return rawStringData(mobj, mobj->d.data[handle]);
}
/*!
@@ -2703,7 +3331,7 @@ const char* QMetaClassInfo::value() const
{
if (!mobj)
return 0;
- return mobj->d.stringdata + mobj->d.data[handle + 1];
+ return rawStringData(mobj, mobj->d.data[handle + 1]);
}
/*!
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 9e51af7556..095b196dca 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -57,8 +57,13 @@ class Q_CORE_EXPORT QMetaMethod
public:
inline QMetaMethod() : mobj(0),handle(0) {}
- const char *signature() const;
+ QByteArray methodSignature() const;
+ QByteArray name() const;
const char *typeName() const;
+ int returnType() const;
+ int parameterCount() const;
+ int parameterType(int index) const;
+ void getParameterTypes(int *types) const;
QList<QByteArray> parameterTypes() const;
QList<QByteArray> parameterNames() const;
const char *tag() const;
@@ -137,8 +142,16 @@ public:
inline bool isValid() const { return mobj != 0; }
private:
+#if QT_DEPRECATED_SINCE(5,0)
+ // signature() has been renamed to methodSignature() in Qt 5.
+ // Warning, that function returns a QByteArray; check the life time if
+ // you convert to char*.
+ char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE;
+#endif
+
const QMetaObject *mobj;
uint handle;
+ friend class QMetaMethodPrivate;
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
friend class QObject;
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 59a5c5f280..ff8dccc4dd 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -105,11 +105,64 @@ enum MetaObjectFlags {
RequiresVariantMetaObject = 0x02
};
+enum MetaDataFlags {
+ IsUnresolvedType = 0x80000000,
+ TypeNameIndexMask = 0x7FFFFFFF
+};
+
+class QArgumentType
+{
+public:
+ QArgumentType(int type)
+ : _type(type)
+ {}
+ QArgumentType(const QByteArray &name)
+ : _type(QMetaType::type(name.constData())), _name(name)
+ {}
+ QArgumentType()
+ : _type(0)
+ {}
+ int type() const
+ { return _type; }
+ QByteArray name() const
+ {
+ if (_type && _name.isEmpty())
+ const_cast<QArgumentType *>(this)->_name = QMetaType::typeName(_type);
+ return _name;
+ }
+ bool operator==(const QArgumentType &other) const
+ {
+ if (_type)
+ return _type == other._type;
+ else if (other._type)
+ return false;
+ else
+ return _name == other._name;
+ }
+ bool operator!=(const QArgumentType &other) const
+ {
+ if (_type)
+ return _type != other._type;
+ else if (other._type)
+ return true;
+ else
+ return _name != other._name;
+ }
+
+private:
+ int _type;
+ QByteArray _name;
+};
+
+template <class T, int> class QVarLengthArray;
+typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray;
+
+class QMetaMethodPrivate;
class QMutex;
struct QMetaObjectPrivate
{
- enum { OutputRevision = 6 }; // Used by moc and qmetaobjectbuilder
+ enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus
int revision;
int className;
@@ -122,6 +175,7 @@ struct QMetaObjectPrivate
int signalCount; //since revision 4
// revision 5 introduces changes in normalized signatures, no new members
// revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
+ // revision 7 is Qt 5
static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
{ return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
@@ -134,6 +188,27 @@ struct QMetaObjectPrivate
bool normalizeStringData);
static int originalClone(const QMetaObject *obj, int local_method_index);
+ static QByteArray decodeMethodSignature(const char *signature,
+ QArgumentTypeArray &types);
+ static int indexOfSignalRelative(const QMetaObject **baseObject,
+ const QByteArray &name, int argc,
+ const QArgumentType *types);
+ static int indexOfSlotRelative(const QMetaObject **m,
+ const QByteArray &name, int argc,
+ const QArgumentType *types);
+ static int indexOfSignal(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types);
+ static int indexOfSlot(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types);
+ static int indexOfMethod(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types);
+ static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
+ int argc, const QArgumentType *types);
+ static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
+ int methodArgc, const QArgumentType *methodTypes);
+ static bool checkConnectArgs(const QMetaMethodPrivate *signal,
+ const QMetaMethodPrivate *method);
+
static QList<QByteArray> parameterTypeNamesFromSignature(const char *signature);
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 8bece6636b..13cd1a684a 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -78,26 +78,17 @@ QT_BEGIN_NAMESPACE
*/
// copied from moc's generator.cpp
-uint qvariant_nameToType(const char* name)
+bool isBuiltinType(const QByteArray &type)
{
- if (!name)
- return 0;
-
- uint tp = QMetaType::type(name);
- return tp < QMetaType::User ? tp : 0;
-}
-
-/*
- Returns true if the type is a QVariant types.
-*/
-bool isVariantType(const char* type)
-{
- return qvariant_nameToType(type) != 0;
+ int id = QMetaType::type(type);
+ if (!id && !type.isEmpty() && type != "void")
+ return false;
+ return (id < QMetaType::User);
}
+// copied from qmetaobject.cpp
static inline const QMetaObjectPrivate *priv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
-// end of copied lines from qmetaobject.cpp
class QMetaMethodBuilderPrivate
{
@@ -136,6 +127,21 @@ public:
{
attributes = ((attributes & ~AccessMask) | (int)value);
}
+
+ QList<QByteArray> parameterTypes() const
+ {
+ return QMetaObjectPrivate::parameterTypeNamesFromSignature(signature);
+ }
+
+ int parameterCount() const
+ {
+ return parameterTypes().size();
+ }
+
+ QByteArray name() const
+ {
+ return signature.left(qMax(signature.indexOf('('), 0));
+ }
};
class QMetaPropertyBuilderPrivate
@@ -458,13 +464,13 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
{
QMetaMethodBuilder method;
if (prototype.methodType() == QMetaMethod::Method)
- method = addMethod(prototype.signature());
+ method = addMethod(prototype.methodSignature());
else if (prototype.methodType() == QMetaMethod::Signal)
- method = addSignal(prototype.signature());
+ method = addSignal(prototype.methodSignature());
else if (prototype.methodType() == QMetaMethod::Slot)
- method = addSlot(prototype.signature());
+ method = addSlot(prototype.methodSignature());
else if (prototype.methodType() == QMetaMethod::Constructor)
- method = addConstructor(prototype.signature());
+ method = addConstructor(prototype.methodSignature());
method.setReturnType(prototype.typeName());
method.setParameterNames(prototype.parameterNames());
method.setTag(prototype.tag());
@@ -535,7 +541,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signatur
QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
{
Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
- QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ QMetaMethodBuilder ctor = addConstructor(prototype.methodSignature());
ctor.setReturnType(prototype.typeName());
ctor.setParameterNames(prototype.parameterNames());
ctor.setTag(prototype.tag());
@@ -588,7 +594,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot
if (prototype.hasNotifySignal()) {
// Find an existing method for the notify signal, or add a new one.
QMetaMethod method = prototype.notifySignal();
- int index = indexOfMethod(method.signature());
+ int index = indexOfMethod(method.methodSignature());
if (index == -1)
index = addMethod(method).index();
d->properties[property._index].notifySignal = index;
@@ -1070,75 +1076,82 @@ int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
#define ALIGN(size,type) \
(size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
-class MetaStringTable
+/*!
+ \class QMetaStringTable
+ \internal
+ \brief The QMetaStringTable class can generate a meta-object string table at runtime.
+*/
+
+QMetaStringTable::QMetaStringTable()
+ : m_index(0) {}
+
+// Enters the given value into the string table (if it hasn't already been
+// entered). Returns the index of the string.
+int QMetaStringTable::enter(const QByteArray &value)
{
-public:
- typedef QHash<QByteArray, int> Entries; // string --> offset mapping
- typedef Entries::const_iterator const_iterator;
- Entries::const_iterator constBegin() const
- { return m_entries.constBegin(); }
- Entries::const_iterator constEnd() const
- { return m_entries.constEnd(); }
+ Entries::iterator it = m_entries.find(value);
+ if (it != m_entries.end())
+ return it.value();
+ int pos = m_index;
+ m_entries.insert(value, pos);
+ ++m_index;
+ return pos;
+}
- MetaStringTable() : m_offset(0) {}
+int QMetaStringTable::preferredAlignment()
+{
+#ifdef Q_ALIGNOF
+ return Q_ALIGNOF(QByteArrayData);
+#else
+ return sizeof(void *);
+#endif
+}
- int enter(const QByteArray &value)
- {
- Entries::iterator it = m_entries.find(value);
- if (it != m_entries.end())
- return it.value();
- int pos = m_offset;
- m_entries.insert(value, pos);
- m_offset += value.size() + 1;
- return pos;
- }
+// Returns the size (in bytes) required for serializing this string table.
+int QMetaStringTable::blobSize() const
+{
+ int size = m_entries.size() * sizeof(QByteArrayData);
+ Entries::const_iterator it;
+ for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it)
+ size += it.key().size() + 1;
+ return size;
+}
- int arraySize() const { return m_offset; }
+// Writes strings to string data struct.
+// The struct consists of an array of QByteArrayData, followed by a char array
+// containing the actual strings. This format must match the one produced by
+// moc (see generator.cpp).
+void QMetaStringTable::writeBlob(char *out)
+{
+ Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1)));
-private:
- Entries m_entries;
- int m_offset;
-};
+ int offsetOfStringdataMember = m_entries.size() * sizeof(QByteArrayData);
+ int stringdataOffset = 0;
+ for (int i = 0; i < m_entries.size(); ++i) {
+ const QByteArray &str = m_entries.key(i);
+ int size = str.size();
+ qptrdiff offset = offsetOfStringdataMember + stringdataOffset
+ - i * sizeof(QByteArrayData);
+ const QByteArrayData data = { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset };
-// Build the parameter array string for a method.
-static QByteArray buildParameterNames
- (const QByteArray& signature, const QList<QByteArray>& parameterNames)
-{
- // If the parameter name list is specified, then concatenate them.
- if (!parameterNames.isEmpty()) {
- QByteArray names;
- bool first = true;
- foreach (const QByteArray &name, parameterNames) {
- if (first)
- first = false;
- else
- names += (char)',';
- names += name;
- }
- return names;
- }
+ memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData));
- // Count commas in the signature, excluding those inside template arguments.
- int index = signature.indexOf('(');
- if (index < 0)
- return QByteArray();
- ++index;
- if (index >= signature.size())
- return QByteArray();
- if (signature[index] == ')')
- return QByteArray();
- int count = 1;
- int brackets = 0;
- while (index < signature.size() && signature[index] != ',') {
- char ch = signature[index++];
- if (ch == '<')
- ++brackets;
- else if (ch == '>')
- --brackets;
- else if (ch == ',' && brackets <= 0)
- ++count;
+ memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size);
+ out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
+
+ stringdataOffset += size + 1;
}
- return QByteArray(count - 1, ',');
+}
+
+// Returns the sum of all parameters (including return type) for the given
+// \a methods. This is needed for calculating the size of the methods'
+// parameter type/name meta-data.
+static int aggregateParameterCount(const QList<QMetaMethodBuilderPrivate> &methods)
+{
+ int sum = 0;
+ for (int i = 0; i < methods.size(); ++i)
+ sum += methods.at(i).parameterCount() + 1; // +1 for return type
+ return sum;
}
// Build a QMetaObject in "buf" based on the information in "d".
@@ -1151,6 +1164,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_UNUSED(expectedSize); // Avoid warning in release mode
int size = 0;
int dataIndex;
+ int paramsIndex;
int enumIndex;
int index;
bool hasRevisionedMethods = d->hasRevisionedMethods();
@@ -1181,8 +1195,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
break;
}
}
+ int methodParametersDataSize =
+ ((aggregateParameterCount(d->methods)
+ + aggregateParameterCount(d->constructors)) * 2) // types and parameter names
+ - d->methods.size() // return "parameters" don't have names
+ - d->constructors.size(); // "this" parameters don't have names
if (buf) {
- Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 6, "QMetaObjectBuilder should generate the same version as moc");
+ Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
pmeta->flags = d->flags;
pmeta->className = 0; // Class name is always the first string.
@@ -1197,6 +1216,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += 5 * d->methods.size();
if (hasRevisionedMethods)
dataIndex += d->methods.size();
+ paramsIndex = dataIndex;
+ dataIndex += methodParametersDataSize;
pmeta->propertyCount = d->properties.size();
pmeta->propertyData = dataIndex;
@@ -1218,6 +1239,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += 5 * d->methods.size();
if (hasRevisionedMethods)
dataIndex += d->methods.size();
+ paramsIndex = dataIndex;
+ dataIndex += methodParametersDataSize;
dataIndex += 3 * d->properties.size();
if (hasNotifySignals)
dataIndex += d->properties.size();
@@ -1240,13 +1263,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Find the start of the data and string tables.
int *data = reinterpret_cast<int *>(pmeta);
size += dataIndex * sizeof(int);
+ ALIGN(size, void *);
char *str = reinterpret_cast<char *>(buf + size);
if (buf) {
if (relocatable) {
- meta->d.stringdata = reinterpret_cast<const char *>((quintptr)size);
+ meta->d.stringdata = reinterpret_cast<const QByteArrayData *>((quintptr)size);
meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize);
} else {
- meta->d.stringdata = str;
+ meta->d.stringdata = reinterpret_cast<const QByteArrayData *>(str);
meta->d.data = reinterpret_cast<uint *>(data);
}
}
@@ -1254,7 +1278,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Reset the current data position to just past the QMetaObjectPrivate.
dataIndex = MetaObjectPrivateFieldCount;
- MetaStringTable strings;
+ QMetaStringTable strings;
strings.enter(d->className);
// Output the class infos,
@@ -1273,24 +1297,21 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
for (index = 0; index < d->methods.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(d->methods[index]);
- int sig = strings.enter(method->signature);
- int params;
- QByteArray names = buildParameterNames
- (method->signature, method->parameterNames);
- params = strings.enter(names);
- int ret = strings.enter(method->returnType);
+ int name = strings.enter(method->name());
+ int argc = method->parameterCount();
int tag = strings.enter(method->tag);
int attrs = method->attributes;
if (buf) {
- data[dataIndex] = sig;
- data[dataIndex + 1] = params;
- data[dataIndex + 2] = ret;
+ data[dataIndex] = name;
+ data[dataIndex + 1] = argc;
+ data[dataIndex + 2] = paramsIndex;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
if (method->methodType() == QMetaMethod::Signal)
pmeta->signalCount++;
}
dataIndex += 5;
+ paramsIndex += 1 + argc * 2;
}
if (hasRevisionedMethods) {
for (index = 0; index < d->methods.size(); ++index) {
@@ -1301,23 +1322,59 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
}
+ // Output the method parameters in the class.
+ Q_ASSERT(!buf || dataIndex == pmeta->methodData + d->methods.size() * 5
+ + (hasRevisionedMethods ? d->methods.size() : 0));
+ for (int x = 0; x < 2; ++x) {
+ QList<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors;
+ for (index = 0; index < methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(methods[index]);
+ QList<QByteArray> paramTypeNames = method->parameterTypes();
+ int paramCount = paramTypeNames.size();
+ for (int i = -1; i < paramCount; ++i) {
+ const QByteArray &typeName = (i < 0) ? method->returnType : paramTypeNames.at(i);
+ int typeInfo;
+ if (isBuiltinType(typeName))
+ typeInfo = QMetaType::type(typeName);
+ else
+ typeInfo = IsUnresolvedType | strings.enter(typeName);
+ if (buf)
+ data[dataIndex] = typeInfo;
+ ++dataIndex;
+ }
+
+ QList<QByteArray> paramNames = method->parameterNames;
+ while (paramNames.size() < paramCount)
+ paramNames.append(QByteArray());
+ for (int i = 0; i < paramCount; ++i) {
+ int stringIndex = strings.enter(paramNames.at(i));
+ if (buf)
+ data[dataIndex] = stringIndex;
+ ++dataIndex;
+ }
+ }
+ }
+
// Output the properties in the class.
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
for (index = 0; index < d->properties.size(); ++index) {
QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
int name = strings.enter(prop->name);
- int type = strings.enter(prop->type);
+
+ int typeInfo;
+ if (isBuiltinType(prop->type))
+ typeInfo = QMetaType::type(prop->type);
+ else
+ typeInfo = IsUnresolvedType | strings.enter(prop->type);
+
int flags = prop->flags;
- if (!isVariantType(prop->type)) {
+ if (!isBuiltinType(prop->type))
flags |= EnumOrFlag;
- } else {
- flags |= qvariant_nameToType(prop->type) << 24;
- }
if (buf) {
data[dataIndex] = name;
- data[dataIndex + 1] = type;
+ data[dataIndex + 1] = typeInfo;
data[dataIndex + 2] = flags;
}
dataIndex += 3;
@@ -1372,34 +1429,25 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
for (index = 0; index < d->constructors.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
- int sig = strings.enter(method->signature);
- int params;
- QByteArray names = buildParameterNames
- (method->signature, method->parameterNames);
- params = strings.enter(names);
- int ret = strings.enter(method->returnType);
+ int name = strings.enter(method->name());
+ int argc = method->parameterCount();
int tag = strings.enter(method->tag);
int attrs = method->attributes;
if (buf) {
- data[dataIndex] = sig;
- data[dataIndex + 1] = params;
- data[dataIndex + 2] = ret;
+ data[dataIndex] = name;
+ data[dataIndex + 1] = argc;
+ data[dataIndex + 2] = paramsIndex;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
}
dataIndex += 5;
+ paramsIndex += 1 + argc * 2;
}
- size += strings.arraySize();
+ size += strings.blobSize();
- if (buf) {
- // Write strings to string data array.
- MetaStringTable::const_iterator it;
- for (it = strings.constBegin(); it != strings.constEnd(); ++it) {
- memcpy(str + it.value(), it.key().constData(), it.key().size());
- str[it.value() + it.key().size()] = '\0';
- }
- }
+ if (buf)
+ strings.writeBlob(str);
// Output the zero terminator in the data array.
if (buf)
@@ -1508,7 +1556,7 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
quintptr dataOffset = (quintptr)dataMo->d.data;
output->d.superdata = superclass;
- output->d.stringdata = buf + stringdataOffset;
+ output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset);
output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
output->d.extradata = 0;
}
@@ -1896,7 +1944,7 @@ QByteArray QMetaMethodBuilder::returnType() const
is empty, then the method's return type is \c{void}. The \a value
will be normalized before it is added to the method.
- \sa returnType(), signature()
+ \sa returnType(), parameterTypes(), signature()
*/
void QMetaMethodBuilder::setReturnType(const QByteArray& value)
{
@@ -1906,6 +1954,20 @@ void QMetaMethodBuilder::setReturnType(const QByteArray& value)
}
/*!
+ Returns the list of parameter types for this method.
+
+ \sa returnType(), parameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterTypes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterTypes();
+ else
+ return QList<QByteArray>();
+}
+
+/*!
Returns the list of parameter names for this method.
\sa setParameterNames()
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index 86bc354164..4d766a9197 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -56,6 +56,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qdatastream.h>
+#include <QtCore/qhash.h>
#include <QtCore/qmap.h>
@@ -203,6 +204,7 @@ public:
QByteArray returnType() const;
void setReturnType(const QByteArray& value);
+ QList<QByteArray> parameterTypes() const;
QList<QByteArray> parameterNames() const;
void setParameterNames(const QList<QByteArray>& value);
@@ -318,6 +320,23 @@ private:
QMetaEnumBuilderPrivate *d_func() const;
};
+class Q_CORE_EXPORT QMetaStringTable
+{
+public:
+ QMetaStringTable();
+
+ int enter(const QByteArray &value);
+
+ static int preferredAlignment();
+ int blobSize() const;
+ void writeBlob(char *out);
+
+private:
+ typedef QHash<QByteArray, int> Entries; // string --> index mapping
+ Entries m_entries;
+ int m_index;
+};
+
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index fc9053520c..8c2b5a8665 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -63,6 +63,7 @@
# include "qurl.h"
# include "qvariant.h"
# include "qabstractitemmodel.h"
+# include "qregularexpression.h"
#endif
#ifndef QT_NO_GEOM_VARIANT
@@ -114,6 +115,9 @@ template<> struct TypeDefinition<QModelIndex> { static const bool IsAvailable =
#ifdef QT_NO_REGEXP
template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = false; };
#endif
+#if defined(QT_BOOTSTRAPPED) || defined(QT_NO_REGEXP)
+template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; };
+#endif
} // namespace
/*!
@@ -219,6 +223,7 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals
\value QPoint QPoint
\value QUrl QUrl
\value QRegExp QRegExp
+ \value QRegularExpression QRegularExpression
\value QDateTime QDateTime
\value QPointF QPointF
\value QPalette QPalette
@@ -242,6 +247,7 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals
\value QEasingCurve QEasingCurve
\value User Base value for user types
+ \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
\omitvalue FirstGuiType
\omitvalue FirstWidgetsType
@@ -311,7 +317,7 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
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)
- {0, 0, QMetaType::Void}
+ {0, 0, QMetaType::UnknownType}
};
Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = 0;
@@ -348,10 +354,7 @@ Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
LoadOperator loadOp)
{
- int idx = type(typeName);
- if (!idx)
- return;
- registerStreamOperators(idx, saveOp, loadOp);
+ registerStreamOperators(type(typeName), saveOp, loadOp);
}
/*! \internal
@@ -435,7 +438,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
{
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (!ct)
- return 0;
+ return QMetaType::UnknownType;
for (int v = 0; v < ct->count(); ++v) {
const QCustomTypeInfo &customInfo = ct->at(v);
@@ -446,7 +449,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
return v + QMetaType::User;
}
}
- return 0;
+ return QMetaType::UnknownType;
}
/*! \internal
@@ -489,11 +492,11 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
int previousSize = 0;
int previousFlags = 0;
- if (!idx) {
+ if (idx == UnknownType) {
QWriteLocker locker(customTypesLock());
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size());
- if (!idx) {
+ if (idx == UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
inf.creator = creator;
@@ -559,12 +562,12 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
normalizedTypeName.size());
- if (!idx) {
+ if (idx == UnknownType) {
QWriteLocker locker(customTypesLock());
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size());
- if (!idx) {
+ if (idx == UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
inf.alias = aliasId;
@@ -593,17 +596,20 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
*/
bool QMetaType::isRegistered(int type)
{
- if (type >= 0 && type < User) {
- // predefined type
+ // predefined type
+ if ((type >= FirstCoreType && type <= LastCoreType)
+ || (type >= FirstGuiType && type <= LastGuiType)
+ || (type >= FirstWidgetsType && type <= LastWidgetsType)) {
return true;
}
+
QReadLocker locker(customTypesLock());
const QVector<QCustomTypeInfo> * const ct = customTypes();
return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
}
/*!
- Returns a handle to the type called \a typeName, or 0 if there is
+ Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
no such type.
\sa isRegistered(), typeName(), Type
@@ -612,17 +618,17 @@ int QMetaType::type(const char *typeName)
{
int length = qstrlen(typeName);
if (!length)
- return 0;
+ return UnknownType;
int type = qMetaTypeStaticType(typeName, length);
- if (!type) {
+ if (type == UnknownType) {
QReadLocker locker(customTypesLock());
type = qMetaTypeCustomType_unlocked(typeName, length);
#ifndef QT_NO_QOBJECT
- if (!type) {
+ if (type == UnknownType) {
const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
type = qMetaTypeStaticType(normalizedTypeName.constData(),
normalizedTypeName.size());
- if (!type) {
+ if (type == UnknownType) {
type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size());
}
@@ -653,6 +659,7 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
return false;
switch(type) {
+ case QMetaType::UnknownType:
case QMetaType::Void:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
@@ -779,10 +786,15 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
break;
#endif
#ifndef QT_BOOTSTRAPPED
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegularExpression:
+ stream << *static_cast<const NS(QRegularExpression)*>(data);
+ break;
+#endif // QT_NO_REGEXP
case QMetaType::QEasingCurve:
stream << *static_cast<const NS(QEasingCurve)*>(data);
break;
-#endif
+#endif // QT_BOOTSTRAPPED
case QMetaType::QFont:
case QMetaType::QPixmap:
case QMetaType::QBrush:
@@ -858,6 +870,7 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
return false;
switch(type) {
+ case QMetaType::UnknownType:
case QMetaType::Void:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
@@ -990,10 +1003,15 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
break;
#endif
#ifndef QT_BOOTSTRAPPED
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegularExpression:
+ stream >> *static_cast< NS(QRegularExpression)*>(data);
+ break;
+#endif // QT_NO_REGEXP
case QMetaType::QEasingCurve:
stream >> *static_cast< NS(QEasingCurve)*>(data);
break;
-#endif
+#endif // QT_BOOTSTRAPPED
case QMetaType::QFont:
case QMetaType::QPixmap:
case QMetaType::QBrush:
@@ -1084,6 +1102,7 @@ public:
template<typename T>
void *delegate(const T *copy) { return CreatorImpl<T>::Create(m_type, copy); }
void *delegate(const void*) { return 0; }
+ void *delegate(const QMetaTypeSwitcher::UnknownType *) { return 0; }
void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy)
{
QMetaType::Creator creator;
@@ -1146,6 +1165,7 @@ public:
template<typename T>
void delegate(const T *where) { DestroyerImpl<T>::Destroy(m_type, const_cast<T*>(where)); }
void delegate(const void *) {}
+ void delegate(const QMetaTypeSwitcher::UnknownType*) {}
void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestroyer(m_type, (void*)where); }
private:
@@ -1209,6 +1229,7 @@ public:
template<typename T>
void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); }
void *delegate(const void *) { return m_where; }
+ void *delegate(const QMetaTypeSwitcher::UnknownType*) { return m_where; }
void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(m_type, m_where, copy); }
private:
@@ -1298,6 +1319,7 @@ public:
template<typename T>
void delegate(const T *where) { DestructorImpl<T>::Destruct(m_type, const_cast<T*>(where)); }
void delegate(const void *) {}
+ void delegate(const QMetaTypeSwitcher::UnknownType*) {}
void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestructor(m_type, (void*)where); }
private:
@@ -1367,6 +1389,7 @@ public:
template<typename T>
int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); }
+ int delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(m_type); }
private:
static int customTypeSizeOf(const int type)
@@ -1433,6 +1456,7 @@ public:
template<typename T>
quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
quint32 delegate(const void*) { return 0; }
+ quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(m_type); }
private:
const int m_type;
@@ -1620,6 +1644,7 @@ public:
template<typename T>
void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
void delegate(const void*) {}
+ void delegate(const QMetaTypeSwitcher::UnknownType*) {}
void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(m_type); }
private:
void customTypeInfo(const uint type)
@@ -1640,7 +1665,7 @@ QMetaType QMetaType::typeInfo(const int type)
{
TypeInfo typeInfo(type);
QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
- return typeInfo.info.creator || !type ? QMetaType(QMetaType::NoExtensionFlags
+ return typeInfo.info.creator || type == Void ? QMetaType(QMetaType::NoExtensionFlags
, static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
, typeInfo.info.creator
, typeInfo.info.deleter
@@ -1651,26 +1676,23 @@ QMetaType QMetaType::typeInfo(const int type)
, typeInfo.info.size
, typeInfo.info.flags
, type)
- : QMetaType(-1);
+ : QMetaType(UnknownType);
}
QMetaType::QMetaType(const int typeId)
: m_typeId(typeId)
{
- if (Q_UNLIKELY(typeId == -1)) {
+ if (Q_UNLIKELY(typeId == UnknownType)) {
// Constructs invalid QMetaType instance.
m_extensionFlags = 0xffffffff;
Q_ASSERT(!isValid());
} else {
// TODO it can be better.
*this = QMetaType::typeInfo(typeId);
- if (m_typeId > 0 && !m_creator) {
+ if (m_typeId == UnknownType)
m_extensionFlags = 0xffffffff;
- m_typeId = -1;
- }
- if (m_typeId == QMetaType::Void) {
+ else if (m_typeId == QMetaType::Void)
m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
- }
}
}
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index bf1b126200..aa73785dac 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
- F(Void, 0, void) \
+ F(Void, 43, void) \
F(Bool, 1, bool) \
F(Int, 2, int) \
F(UInt, 3, uint) \
@@ -102,6 +102,7 @@ QT_BEGIN_NAMESPACE
F(QUuid, 30, QUuid) \
F(QVariant, 41, QVariant) \
F(QModelIndex, 42, QModelIndex) \
+ F(QRegularExpression, 44, QRegularExpression)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
F(QObjectStar, 39, QObject*) \
@@ -193,8 +194,8 @@ public:
// these are merged with QVariant
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
- FirstCoreType = Void,
- LastCoreType = QModelIndex,
+ FirstCoreType = Bool,
+ LastCoreType = QRegularExpression,
FirstGuiType = QFont,
LastGuiType = QPolygonF,
FirstWidgetsType = QIcon,
@@ -203,6 +204,7 @@ public:
QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
+ UnknownType = 0,
User = 256
};
@@ -366,33 +368,11 @@ void qMetaTypeLoadHelper(QDataStream &stream, void *t)
template <> inline void qMetaTypeLoadHelper<void>(QDataStream &, void *) {}
#endif // QT_NO_DATASTREAM
-template <typename T>
-struct QMetaTypeId
-{
- enum { Defined = 0 };
-};
-
-template <typename T>
-struct QMetaTypeId2
-{
- enum { Defined = QMetaTypeId<T>::Defined };
- static inline int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
-};
-
class QObject;
class QWidget;
-namespace QtPrivate {
- template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
- struct QMetaTypeIdHelper {
- static inline int qt_metatype_id()
- { return QMetaTypeId2<T>::qt_metatype_id(); }
- };
- template <typename T> struct QMetaTypeIdHelper<T, false> {
- static inline int qt_metatype_id()
- { return -1; }
- };
-
+namespace QtPrivate
+{
template<typename T>
struct IsPointerToTypeDerivedFromQObject
{
@@ -429,6 +409,38 @@ namespace QtPrivate {
Q_STATIC_ASSERT_X(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined");
enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(yes_type) };
};
+}
+
+template <typename T, bool = QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value>
+struct QMetaTypeIdQObject
+{
+ enum {
+ Defined = 0
+ };
+};
+
+template <typename T>
+struct QMetaTypeId : public QMetaTypeIdQObject<T>
+{
+};
+
+template <typename T>
+struct QMetaTypeId2
+{
+ enum { Defined = QMetaTypeId<T>::Defined };
+ static inline int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
+};
+
+namespace QtPrivate {
+ template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
+ struct QMetaTypeIdHelper {
+ static inline int qt_metatype_id()
+ { return QMetaTypeId2<T>::qt_metatype_id(); }
+ };
+ template <typename T> struct QMetaTypeIdHelper<T, false> {
+ static inline int qt_metatype_id()
+ { return -1; }
+ };
// Function pointers don't derive from QObject
template <class Result> struct IsPointerToTypeDerivedFromQObject<Result(*)()> { enum { Value = false }; };
@@ -506,6 +518,23 @@ inline int qRegisterMetaType(
#endif
}
+template <typename T>
+struct QMetaTypeIdQObject<T*, /* isPointerToTypeDerivedFromQObject */ true>
+{
+ enum {
+ Defined = 1
+ };
+
+ static int qt_metatype_id()
+ {
+ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if (!metatype_id.load())
+ metatype_id.storeRelease(qRegisterMetaType<T*>(QByteArray(T::staticMetaObject.className() + QByteArrayLiteral("*")).constData(),
+ reinterpret_cast<T**>(quintptr(-1))));
+ return metatype_id.loadAcquire();
+ }
+};
+
#ifndef QT_NO_DATASTREAM
template <typename T>
inline int qRegisterMetaTypeStreamOperators()
@@ -654,7 +683,7 @@ inline QMetaType::~QMetaType()
inline bool QMetaType::isValid() const
{
- return m_typeId >= 0;
+ return m_typeId != UnknownType;
}
inline bool QMetaType::isRegistered() const
diff --git a/src/corelib/kernel/qmetatypeswitcher_p.h b/src/corelib/kernel/qmetatypeswitcher_p.h
index e9c15ea214..ffd188c972 100644
--- a/src/corelib/kernel/qmetatypeswitcher_p.h
+++ b/src/corelib/kernel/qmetatypeswitcher_p.h
@@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE
class QMetaTypeSwitcher {
public:
- class NotBuiltinType;
+ class NotBuiltinType; // type is not a built-in type, but it may be a custom type or an unknown type
+ class UnknownType; // type not known to QMetaType system
template<class ReturnType, class DelegateObject>
static ReturnType switcher(DelegateObject &logic, int type, const void *data);
};
@@ -74,7 +75,11 @@ ReturnType QMetaTypeSwitcher::switcher(DelegateObject &logic, int type, const vo
switch (QMetaType::Type(type)) {
QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_SWICHER_CASE)
+ case QMetaType::UnknownType:
+ return logic.delegate(static_cast<UnknownType const *>(data));
default:
+ if (type < QMetaType::User)
+ return logic.delegate(static_cast<UnknownType const *>(data));
return logic.delegate(static_cast<NotBuiltinType const *>(data));
}
}
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index b648432e11..914441f7a8 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -105,6 +105,30 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
return types;
}
+static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
+{
+ QScopedArrayPointer<int> types(new int [argc + 1]);
+ for (int i = 0; i < argc; ++i) {
+ const QArgumentType &type = argumentTypes[i];
+ if (type.type())
+ types[i] = type.type();
+ else if (type.name().endsWith('*'))
+ types[i] = QMetaType::VoidStar;
+ else
+ types[i] = QMetaType::type(type.name());
+
+ if (!types[i]) {
+ qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
+ "(Make sure '%s' is registered using qRegisterMetaType().)",
+ type.name().constData(), type.name().constData());
+ return 0;
+ }
+ }
+ types[argc] = 0;
+
+ return types.take();
+}
+
static QBasicMutex _q_ObjectMutexPool[131];
/** \internal
@@ -2179,12 +2203,12 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
if (signal.attributes() & QMetaMethod::Compatibility) {
if (!(method.attributes() & QMetaMethod::Compatibility))
qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
- sender->className(), signal.signature());
+ sender->className(), signal.methodSignature().constData());
} else if ((method.attributes() & QMetaMethod::Compatibility) &&
method.methodType() == QMetaMethod::Signal) {
qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
- sender->className(), signal.signature(),
- receiver->className(), method.signature());
+ sender->className(), signal.methodSignature().constData(),
+ receiver->className(), method.methodSignature().constData());
}
}
@@ -2283,20 +2307,40 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
const QMetaObject *smeta = sender->metaObject();
const char *signal_arg = signal;
++signal; //skip code
- int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
- if (signal_index < 0) {
- // check for normalized signatures
- tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
- signal = tmp_signal_name.constData() + 1;
-
- smeta = sender->metaObject();
+ QByteArray signalName;
+ QArgumentTypeArray signalTypes;
+ int signal_index;
+ if (QMetaObjectPrivate::get(smeta)->revision >= 7) {
+ signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(
+ &smeta, signalName, signalTypes.size(), signalTypes.constData());
+ if (signal_index < 0) {
+ // check for normalized signatures
+ tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
+ signal = tmp_signal_name.constData() + 1;
+
+ signalTypes.clear();
+ signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(
+ &smeta, signalName, signalTypes.size(), signalTypes.constData());
+ }
+ } else {
signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
- }
- if (signal_index < 0) {
- // re-use tmp_signal_name and signal from above
+ if (signal_index < 0) {
+ // check for normalized signatures
+ tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
+ signal = tmp_signal_name.constData() + 1;
+
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ if (signal_index < 0) {
+ // re-use tmp_signal_name and signal from above
- smeta = sender->metaObject();
- signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ }
+ }
}
if (signal_index < 0) {
err_method_notfound(sender, signal_arg, "connect");
@@ -2317,36 +2361,71 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
const char *method_arg = method;
++method; // skip code
+ QByteArray methodName;
+ QArgumentTypeArray methodTypes;
const QMetaObject *rmeta = receiver->metaObject();
int method_index_relative = -1;
- switch (membcode) {
- case QSLOT_CODE:
- method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
- break;
- case QSIGNAL_CODE:
- method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
- break;
- }
-
- if (method_index_relative < 0) {
- // check for normalized methods
- tmp_method_name = QMetaObject::normalizedSignature(method);
- method = tmp_method_name.constData();
-
- // rmeta may have been modified above
- rmeta = receiver->metaObject();
+ if (QMetaObjectPrivate::get(rmeta)->revision >= 7) {
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
+ &rmeta, methodName, methodTypes.size(), methodTypes.constData());
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
+ &rmeta, methodName, methodTypes.size(), methodTypes.constData());
+ break;
+ }
+ if (method_index_relative < 0) {
+ // check for normalized methods
+ tmp_method_name = QMetaObject::normalizedSignature(method);
+ method = tmp_method_name.constData();
+
+ methodTypes.clear();
+ methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
+ // rmeta may have been modified above
+ rmeta = receiver->metaObject();
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
+ &rmeta, methodName, methodTypes.size(), methodTypes.constData());
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
+ &rmeta, methodName, methodTypes.size(), methodTypes.constData());
+ break;
+ }
+ }
+ } else {
switch (membcode) {
case QSLOT_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
- if (method_index_relative < 0)
- method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
break;
case QSIGNAL_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
- if (method_index_relative < 0)
- method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
break;
}
+
+ if (method_index_relative < 0) {
+ // check for normalized methods
+ tmp_method_name = QMetaObject::normalizedSignature(method);
+ method = tmp_method_name.constData();
+
+ // rmeta may have been modified above
+ rmeta = receiver->metaObject();
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
+ break;
+ }
+ }
}
if (method_index_relative < 0) {
@@ -2355,7 +2434,18 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
return QMetaObject::Connection(0);
}
- if (!QMetaObject::checkConnectArgs(signal, method)) {
+ bool compatibleArgs = true;
+ if ((QMetaObjectPrivate::get(smeta)->revision < 7) && (QMetaObjectPrivate::get(rmeta)->revision < 7)) {
+ compatibleArgs = QMetaObject::checkConnectArgs(signal, method);
+ } else {
+ if (signalName.isEmpty())
+ signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
+ if (methodName.isEmpty())
+ methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
+ compatibleArgs = QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
+ methodTypes.size(), methodTypes.constData());
+ }
+ if (!compatibleArgs) {
qWarning("QObject::connect: Incompatible sender/receiver arguments"
"\n %s::%s --> %s::%s",
sender->metaObject()->className(), signal,
@@ -2365,8 +2455,11 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
int *types = 0;
if ((type == Qt::QueuedConnection)
- && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
+ && ((QMetaObjectPrivate::get(smeta)->revision >= 7)
+ ? !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))
+ : !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))) {
return QMetaObject::Connection(0);
+ }
#ifndef QT_NO_DEBUG
if (warnCompat) {
@@ -2424,17 +2517,17 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
|| method.methodType() == QMetaMethod::Constructor) {
qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
sender ? sender->metaObject()->className() : "(null)",
- signal.signature(),
+ signal.methodSignature().constData(),
receiver ? receiver->metaObject()->className() : "(null)",
- method.signature() );
+ method.methodSignature().constData() );
return QMetaObject::Connection(0);
}
- // Reconstructing SIGNAL() macro result for signal.signature() string
+ // Reconstructing SIGNAL() macro result for signal.methodSignature() string
QByteArray signalSignature;
- signalSignature.reserve(qstrlen(signal.signature())+1);
+ signalSignature.reserve(signal.methodSignature().size()+1);
signalSignature.append((char)(QSIGNAL_CODE + '0'));
- signalSignature.append(signal.signature());
+ signalSignature.append(signal.methodSignature());
int signal_index;
int method_index;
@@ -2448,20 +2541,20 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
const QMetaObject *rmeta = receiver->metaObject();
if (signal_index == -1) {
qWarning("QObject::connect: Can't find signal %s on instance of class %s",
- signal.signature(), smeta->className());
+ signal.methodSignature().constData(), smeta->className());
return QMetaObject::Connection(0);
}
if (method_index == -1) {
qWarning("QObject::connect: Can't find method %s on instance of class %s",
- method.signature(), rmeta->className());
+ method.methodSignature().constData(), rmeta->className());
return QMetaObject::Connection(0);
}
- if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
+ if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
qWarning("QObject::connect: Incompatible sender/receiver arguments"
"\n %s::%s --> %s::%s",
- smeta->className(), signal.signature(),
- rmeta->className(), method.signature());
+ smeta->className(), signal.methodSignature().constData(),
+ rmeta->className(), method.methodSignature().constData());
return QMetaObject::Connection(0);
}
@@ -2609,12 +2702,25 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
*/
bool res = false;
const QMetaObject *smeta = sender->metaObject();
+ QByteArray signalName;
+ QArgumentTypeArray signalTypes;
+ if (signal && (QMetaObjectPrivate::get(smeta)->revision >= 7))
+ signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
+ QByteArray methodName;
+ QArgumentTypeArray methodTypes;
+ if (method && (QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7))
+ methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
do {
int signal_index = -1;
if (signal) {
- signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
- if (signal_index < 0)
- signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ if (QMetaObjectPrivate::get(smeta)->revision >= 7) {
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(
+ &smeta, signalName, signalTypes.size(), signalTypes.constData());
+ } else {
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ if (signal_index < 0)
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ }
if (signal_index < 0)
break;
signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
@@ -2629,7 +2735,13 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
} else {
const QMetaObject *rmeta = receiver->metaObject();
do {
- int method_index = rmeta->indexOfMethod(method);
+ int method_index;
+ if (QMetaObjectPrivate::get(rmeta)->revision >= 7) {
+ method_index = QMetaObjectPrivate::indexOfMethod(
+ rmeta, methodName, methodTypes.size(), methodTypes.constData());
+ } else {
+ method_index = rmeta->indexOfMethod(method);
+ }
if (method_index >= 0)
while (method_index < rmeta->methodOffset())
rmeta = rmeta->superClass();
@@ -2693,24 +2805,24 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
if(signal.methodType() != QMetaMethod::Signal) {
qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
"disconnect","unbind",
- sender->metaObject()->className(), signal.signature());
+ sender->metaObject()->className(), signal.methodSignature().constData());
return false;
}
}
if (method.mobj) {
if(method.methodType() == QMetaMethod::Constructor) {
qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
- receiver->metaObject()->className(), method.signature());
+ receiver->metaObject()->className(), method.methodSignature().constData());
return false;
}
}
- // Reconstructing SIGNAL() macro result for signal.signature() string
+ // Reconstructing SIGNAL() macro result for signal.methodSignature() string
QByteArray signalSignature;
if (signal.mobj) {
- signalSignature.reserve(qstrlen(signal.signature())+1);
+ signalSignature.reserve(signal.methodSignature().size()+1);
signalSignature.append((char)(QSIGNAL_CODE + '0'));
- signalSignature.append(signal.signature());
+ signalSignature.append(signal.methodSignature());
}
int signal_index;
@@ -2724,13 +2836,13 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
// is -1 then this signal is not a member of sender.
if (signal.mobj && signal_index == -1) {
qWarning("QObject::disconect: signal %s not found on class %s",
- signal.signature(), sender->metaObject()->className());
+ signal.methodSignature().constData(), sender->metaObject()->className());
return false;
}
// If this condition is true then method is not a member of receeiver.
if (receiver && method.mobj && method_index == -1) {
qWarning("QObject::disconect: method %s not found on class %s",
- method.signature(), receiver->metaObject()->className());
+ method.methodSignature().constData(), receiver->metaObject()->className());
return false;
}
@@ -3045,7 +3157,8 @@ void QMetaObject::connectSlotsByName(QObject *o)
Q_ASSERT(mo);
const QObjectList list = o->findChildren<QObject *>(QString());
for (int i = 0; i < mo->methodCount(); ++i) {
- const char *slot = mo->method(i).signature();
+ QByteArray slotSignature = mo->method(i).methodSignature();
+ const char *slot = slotSignature.constData();
Q_ASSERT(slot);
if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
continue;
@@ -3065,7 +3178,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
if (method.methodType() != QMetaMethod::Signal)
continue;
- if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
+ if (!qstrncmp(method.methodSignature().constData(), slot + len + 4, slotlen)) {
int signalOffset, methodOffset;
computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
sigIndex = k + - methodOffset + signalOffset;
@@ -3311,9 +3424,17 @@ int QObjectPrivate::signalIndex(const char *signalName) const
{
Q_Q(const QObject);
const QMetaObject *base = q->metaObject();
- int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
- if (relative_index < 0)
- relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
+ int relative_index;
+ if (QMetaObjectPrivate::get(base)->revision >= 7) {
+ QArgumentTypeArray types;
+ QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signalName, types);
+ relative_index = QMetaObjectPrivate::indexOfSignalRelative(
+ &base, name, types.size(), types.constData());
+ } else {
+ relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
+ if (relative_index < 0)
+ relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
+ }
if (relative_index < 0)
return relative_index;
relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
@@ -3536,7 +3657,7 @@ void QObject::dumpObjectInfo()
offset = methodOffset - signalOffset;
}
const QMetaMethod signal = metaObject()->method(signal_index + offset);
- qDebug(" signal: %s", signal.signature());
+ qDebug(" signal: %s", signal.methodSignature().constData());
// receivers
const QObjectPrivate::Connection *c =
@@ -3552,7 +3673,7 @@ void QObject::dumpObjectInfo()
qDebug(" --> %s::%s %s",
receiverMetaObject->className(),
c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
- method.signature());
+ method.methodSignature().constData());
c = c->nextConnectionList;
}
}
@@ -3569,7 +3690,7 @@ void QObject::dumpObjectInfo()
qDebug(" <-- %s::%s %s",
s->sender->metaObject()->className(),
s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
- slot.signature());
+ slot.methodSignature().constData());
}
} else {
qDebug(" <None>");
@@ -4041,9 +4162,16 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
locker.unlock();
// reconstruct the signature to call connectNotify
- const char *sig = senderMetaObject->d.stringdata + senderMetaObject->d.data[
- reinterpret_cast<const QMetaObjectPrivate*>(senderMetaObject->d.data)->methodData
- + 5 * (signal_index - signalOffset)];
+ QByteArray tmp_sig;
+ const char *sig;
+ if (QMetaObjectPrivate::get(senderMetaObject)->revision >= 7) {
+ tmp_sig = senderMetaObject->method(signal_index - signalOffset + methodOffset).methodSignature();
+ sig = tmp_sig.constData();
+ } else {
+ sig = reinterpret_cast<const char *>(senderMetaObject->d.stringdata)
+ + senderMetaObject->d.data[QMetaObjectPrivate::get(senderMetaObject)->methodData
+ + 5 * (signal_index - signalOffset)];
+ }
QVarLengthArray<char> signalSignature(qstrlen(sig) + 2);
signalSignature.data()[0] = char(QSIGNAL_CODE + '0');
strcpy(signalSignature.data() + 1 , sig);
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 4b3829b53e..4c98bad0f9 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -50,11 +50,12 @@ QT_BEGIN_NAMESPACE
class QByteArray;
+struct QByteArrayData;
class QString;
#ifndef Q_MOC_OUTPUT_REVISION
-#define Q_MOC_OUTPUT_REVISION 64
+#define Q_MOC_OUTPUT_REVISION 65
#endif
// The following macros are our "extensions" to C++
@@ -326,6 +327,8 @@ struct Q_CORE_EXPORT QMetaObject
QMetaProperty userProperty() const;
static bool checkConnectArgs(const char *signal, const char *method);
+ static bool checkConnectArgs(const QMetaMethod &signal,
+ const QMetaMethod &method);
static QByteArray normalizedSignature(const char *method);
static QByteArray normalizedType(const char *type);
@@ -439,7 +442,7 @@ struct Q_CORE_EXPORT QMetaObject
struct { // private data
const QMetaObject *superdata;
- const char *stringdata;
+ const QByteArrayData *stringdata;
const uint *data;
const void *extradata;
} d;
@@ -480,9 +483,6 @@ struct QMetaObjectExtraData
StaticMetacallFunction static_metacall;
};
-inline const char *QMetaObject::className() const
-{ return d.stringdata; }
-
inline const QMetaObject *QMetaObject::superClass() const
{ return d.superdata; }
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index e630b5bba8..e08f4ef53c 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -48,6 +48,7 @@
#include "qdatetime.h"
#include "qeasingcurve.h"
#include "qlist.h"
+#include "qregularexpression.h"
#include "qstring.h"
#include "qstringlist.h"
#include "qurl.h"
@@ -106,6 +107,7 @@ struct TypeDefinition {
#ifdef QT_BOOTSTRAPPED
template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QModelIndex> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; };
#endif
#ifdef QT_NO_GEOM_VARIANT
template<> struct TypeDefinition<QRect> { static const bool IsAvailable = false; };
@@ -1028,6 +1030,7 @@ Q_CORE_EXPORT void QVariantPrivate::unregisterHandler(const int /* Modules::Name
\value Rect a QRect
\value RectF a QRectF
\value RegExp a QRegExp
+ \value RegularExpression a QRegularExpression
\value Region a QRegion
\value Size a QSize
\value SizeF a QSizeF
@@ -1358,6 +1361,14 @@ QVariant::QVariant(const char *val)
Constructs a new variant with the regexp value \a regExp.
*/
+/*!
+ \fn QVariant::QVariant(const QRegularExpression &re)
+
+ \since 5.0
+
+ Constructs a new variant with the regular expression value \a re.
+*/
+
/*! \since 4.2
\fn QVariant::QVariant(Qt::GlobalColor color)
@@ -1446,7 +1457,10 @@ QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct
QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); }
#ifndef QT_NO_REGEXP
QVariant::QVariant(const QRegExp &regExp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); }
-#endif
+#ifndef QT_BOOTSTRAPPED
+QVariant::QVariant(const QRegularExpression &re) { d.is_null = false; d.type = QMetaType::QRegularExpression; v_construct<QRegularExpression>(&d, re); }
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); }
/*!
@@ -1697,7 +1711,7 @@ void QVariant::load(QDataStream &s)
QByteArray name;
s >> name;
typeId = QMetaType::type(name.constData());
- if (!typeId) {
+ if (typeId == QMetaType::UnknownType) {
s.setStatus(QDataStream::ReadCorruptData);
return;
}
@@ -2127,6 +2141,24 @@ QRegExp QVariant::toRegExp() const
#endif
/*!
+ \fn QRegularExpression QVariant::toRegularExpression() const
+ \since 5.0
+
+ Returns the variant as a QRegularExpression if the variant has type() \l
+ QRegularExpression; otherwise returns an empty QRegularExpression.
+
+ \sa canConvert(), convert()
+*/
+#ifndef QT_BOOTSTRAPPED
+#ifndef QT_NO_REGEXP
+QRegularExpression QVariant::toRegularExpression() const
+{
+ return qVariantToHelper<QRegularExpression>(d, handlerManager);
+}
+#endif
+#endif
+
+/*!
\fn QChar QVariant::toChar() const
Returns the variant as a QChar if the variant has type() \l Char,
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 5da482d5cd..cc502d93a7 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -76,7 +76,8 @@ class QRect;
class QRectF;
#ifndef QT_NO_REGEXP
class QRegExp;
-#endif
+class QRegularExpression;
+#endif // QT_NO_REGEXP
class QTextFormat;
class QTextLength;
class QUrl;
@@ -126,7 +127,7 @@ class Q_CORE_EXPORT QVariant
{
public:
enum Type {
- Invalid = QMetaType::Void,
+ Invalid = QMetaType::UnknownType,
Bool = QMetaType::Bool,
Int = QMetaType::Int,
UInt = QMetaType::UInt,
@@ -154,6 +155,7 @@ class Q_CORE_EXPORT QVariant
Point = QMetaType::QPoint,
PointF = QMetaType::QPointF,
RegExp = QMetaType::QRegExp,
+ RegularExpression = QMetaType::QRegularExpression,
Hash = QMetaType::QVariantHash,
EasingCurve = QMetaType::QEasingCurve,
Uuid = QMetaType::QUuid,
@@ -239,7 +241,10 @@ class Q_CORE_EXPORT QVariant
QVariant(const QLocale &locale);
#ifndef QT_NO_REGEXP
QVariant(const QRegExp &regExp);
-#endif
+#ifndef QT_BOOTSRAPPED
+ QVariant(const QRegularExpression &re);
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
#ifndef QT_BOOTSTRAPPED
QVariant(const QEasingCurve &easing);
#endif
@@ -302,7 +307,10 @@ class Q_CORE_EXPORT QVariant
QLocale toLocale() const;
#ifndef QT_NO_REGEXP
QRegExp toRegExp() const;
-#endif
+#ifndef QT_BOOTSTRAPPED
+ QRegularExpression toRegularExpression() const;
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
#ifndef QT_BOOTSTRAPPED
QEasingCurve toEasingCurve() const;
#endif
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index a754bc4363..90756d76cc 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -187,7 +187,11 @@ public:
return FilteredComparator<T>::compare(m_a, m_b);
}
- bool delegate(const void*) { return true; }
+ bool delegate(const void*) { Q_ASSERT(false); return true; }
+ bool delegate(const QMetaTypeSwitcher::UnknownType*)
+ {
+ return true; // for historical reason invalid variant == invalid variant
+ }
bool delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return false; }
protected:
const QVariant::Private *m_a;
@@ -203,6 +207,19 @@ class QVariantIsNull
/// \internal
/// This class checks if a type T has method called isNull. Result is kept in the Value property
/// TODO Can we somehow generalize it? A macro version?
+#if defined(Q_COMPILER_DECLTYPE) // C++11 version
+ template<typename T>
+ class HasIsNullMethod {
+ struct Yes { char unused[1]; };
+ struct No { char unused[2]; };
+ Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No));
+
+ template<class C> static decltype(static_cast<const C*>(0)->isNull(), Yes()) test(int);
+ template<class C> static No test(...);
+ public:
+ static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes));
+ };
+#else // C++98 version (doesn't work for final classes)
template<typename T, bool IsClass = QTypeInfo<T>::isComplex>
class HasIsNullMethod
{
@@ -211,7 +228,7 @@ class QVariantIsNull
Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No));
struct FallbackMixin { bool isNull() const; };
- struct Derived : public T, public FallbackMixin {};
+ struct Derived : public T, public FallbackMixin {}; // <- doesn't work for final classes
template<class C, C> struct TypeCheck {};
template<class C> static Yes test(...);
@@ -227,6 +244,7 @@ class QVariantIsNull
public:
static const bool Value = false;
};
+#endif
// TODO This part should go to autotests during HasIsNullMethod generalization.
Q_STATIC_ASSERT(!HasIsNullMethod<bool>::Value);
@@ -236,6 +254,12 @@ class QVariantIsNull
Q_STATIC_ASSERT(!HasIsNullMethod<SelfTest2>::Value);
struct SelfTest3 : public SelfTest1 {};
Q_STATIC_ASSERT(HasIsNullMethod<SelfTest3>::Value);
+ struct SelfTestFinal1 Q_DECL_FINAL_CLASS { bool isNull() const; };
+ Q_STATIC_ASSERT(HasIsNullMethod<SelfTestFinal1>::Value);
+ struct SelfTestFinal2 Q_DECL_FINAL_CLASS {};
+ Q_STATIC_ASSERT(!HasIsNullMethod<SelfTestFinal2>::Value);
+ struct SelfTestFinal3 Q_DECL_FINAL_CLASS : public SelfTest1 {};
+ Q_STATIC_ASSERT(HasIsNullMethod<SelfTestFinal3>::Value);
template<typename T, bool HasIsNull = HasIsNullMethod<T>::Value>
struct CallFilteredIsNull
@@ -281,7 +305,8 @@ public:
return CallIsNull<T>::isNull(m_d);
}
// we need that as sizof(void) is undefined and it is needed in HasIsNullMethod
- bool delegate(const void *) { return m_d->is_null; }
+ bool delegate(const void *) { Q_ASSERT(false); return m_d->is_null; }
+ bool delegate(const QMetaTypeSwitcher::UnknownType *) { return m_d->is_null; }
bool delegate(const QMetaTypeSwitcher::NotBuiltinType *) { return m_d->is_null; }
protected:
const QVariant::Private *m_d;
@@ -354,8 +379,18 @@ public:
void delegate(const void*)
{
- // QMetaType::Void == QVariant::Invalid, creating an invalid value creates invalid QVariant
- // TODO it might go away, check is needed
+ qWarning("Trying to create a QVariant instance of QMetaType::Void type, an invalid QVariant will be constructed instead");
+ m_x->type = QMetaType::UnknownType;
+ m_x->is_shared = false;
+ m_x->is_null = !m_copy;
+ }
+
+ void delegate(const QMetaTypeSwitcher::UnknownType*)
+ {
+ if (m_x->type != QMetaType::UnknownType) {
+ qWarning("Trying to construct an instance of an invalid type, type id: %i", m_x->type);
+ m_x->type = QMetaType::UnknownType;
+ }
m_x->is_shared = false;
m_x->is_null = !m_copy;
}
@@ -401,7 +436,8 @@ public:
qWarning("Trying to destruct an instance of an invalid type, type id: %i", m_d->type);
}
// Ignore nonconstructible type
- void delegate(const void*) {}
+ void delegate(const QMetaTypeSwitcher::UnknownType*) {}
+ void delegate(const void*) { Q_ASSERT(false); }
private:
QVariant::Private *m_d;
};
@@ -446,10 +482,11 @@ public:
{
qWarning("Trying to stream an instance of an invalid type, type id: %i", m_d->type);
}
- void delegate(const void*)
+ void delegate(const QMetaTypeSwitcher::UnknownType*)
{
m_debugStream.nospace() << "QVariant::Invalid";
}
+ void delegate(const void*) { Q_ASSERT(false); }
private:
QDebug m_debugStream;
QVariant::Private *m_d;
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 7ff005f9a1..be96d895a2 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1657,7 +1657,7 @@ void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalInd
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q_func() << ": sending signal event ( sender =" << sender
- << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
+ << ", signal =" << sender->metaObject()->method(signalIndex).methodSignature().constData() << ')';
#endif
postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
processEvents(DirectProcessing);
@@ -2211,10 +2211,29 @@ void QStateMachine::removeDefaultAnimation(QAbstractAnimation *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_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \
+ 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:
- 6, // revision
+ 7, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
@@ -2224,14 +2243,13 @@ static const uint qt_meta_data_QSignalEventGenerator[] = {
0, // flags
0, // signalCount
- // slots: signature, parameters, type, tag, flags
- 23, 22, 22, 22, 0x0a,
+ // slots: name, argc, parameters, tag, flags
+ 1, 0, 19, 2, 0x0a,
- 0 // eod
-};
+ // slots: parameters
+ QMetaType::Void,
-static const char qt_meta_stringdata_QSignalEventGenerator[] = {
- "QSignalEventGenerator\0\0execute()\0"
+ 0 // eod
};
void QSignalEventGenerator::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
@@ -2252,7 +2270,7 @@ const QMetaObjectExtraData QSignalEventGenerator::staticMetaObjectExtraData = {
};
const QMetaObject QSignalEventGenerator::staticMetaObject = {
- { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator,
+ { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator.data,
qt_meta_data_QSignalEventGenerator, &staticMetaObjectExtraData }
};
@@ -2264,7 +2282,7 @@ const QMetaObject *QSignalEventGenerator::metaObject() const
void *QSignalEventGenerator::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
+ if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator.stringdata))
return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
return QObject::qt_metacast(_clname);
}
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index c9c60976d1..b3aeb41016 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -119,7 +119,7 @@ public:
NoCommonAncestorForTransitionError
};
- QStateMachine(QObject *parent = 0);
+ explicit QStateMachine(QObject *parent = 0);
~QStateMachine();
void addState(QAbstractState *state);
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
new file mode 100644
index 0000000000..8498d0e4d5
--- /dev/null
+++ b/src/corelib/tools/qarraydata.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qarraydata.h>
+#include <QtCore/private/qtools_p.h>
+
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+const QArrayData QArrayData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
+
+static const QArrayData qt_array_empty = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
+static const QArrayData qt_array_unsharable_empty = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 };
+
+QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
+ size_t capacity, AllocationOptions options)
+{
+ // Alignment is a power of two
+ Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
+ && !(alignment & (alignment - 1)));
+
+ // Don't allocate empty headers
+ if (!(options & RawData) && !capacity)
+ return !(options & Unsharable)
+ ? const_cast<QArrayData *>(&qt_array_empty)
+ : const_cast<QArrayData *>(&qt_array_unsharable_empty);
+
+ 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));
+
+ // Allocate additional space if array is growing
+ if (options & Grow)
+ capacity = qAllocMore(objectSize * capacity, headerSize) / objectSize;
+
+ size_t allocSize = headerSize + objectSize * capacity;
+
+ QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
+ if (header) {
+ quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
+ & ~(alignment - 1);
+
+ header->ref.atomic.store(bool(!(options & Unsharable)));
+ header->size = 0;
+ header->alloc = capacity;
+ header->capacityReserved = bool(options & CapacityReserved);
+ header->offset = data - quintptr(header);
+ }
+
+ return header;
+}
+
+void QArrayData::deallocate(QArrayData *data, size_t objectSize,
+ size_t alignment)
+{
+ // Alignment is a power of two
+ Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
+ && !(alignment & (alignment - 1)));
+ Q_UNUSED(objectSize) Q_UNUSED(alignment)
+
+ if (data == &qt_array_unsharable_empty)
+ return;
+
+ ::free(data);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
new file mode 100644
index 0000000000..351a75aade
--- /dev/null
+++ b/src/corelib/tools/qarraydata.h
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QARRAYDATA_H
+#define QARRAYDATA_H
+
+#include <QtCore/qrefcount.h>
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+struct Q_CORE_EXPORT QArrayData
+{
+ QtPrivate::RefCount ref;
+ int size;
+ uint alloc : 31;
+ uint capacityReserved : 1;
+
+ qptrdiff offset; // in bytes from beginning of header
+
+ void *data()
+ {
+ Q_ASSERT(size == 0
+ || offset < 0 || size_t(offset) >= sizeof(QArrayData));
+ return reinterpret_cast<char *>(this) + offset;
+ }
+
+ const void *data() const
+ {
+ Q_ASSERT(size == 0
+ || offset < 0 || size_t(offset) >= sizeof(QArrayData));
+ return reinterpret_cast<const char *>(this) + offset;
+ }
+
+ // This refers to array data mutability, not "header data" represented by
+ // data members in QArrayData. Shared data (array and header) must still
+ // follow COW principles.
+ bool isMutable() const
+ {
+ return alloc != 0;
+ }
+
+ enum AllocationOption {
+ CapacityReserved = 0x1,
+ Unsharable = 0x2,
+ RawData = 0x4,
+ Grow = 0x8,
+
+ Default = 0
+ };
+
+ Q_DECLARE_FLAGS(AllocationOptions, AllocationOption)
+
+ AllocationOptions detachFlags() const
+ {
+ AllocationOptions result;
+ if (!ref.isSharable())
+ result |= Unsharable;
+ if (capacityReserved)
+ result |= CapacityReserved;
+ return result;
+ }
+
+ AllocationOptions cloneFlags() const
+ {
+ AllocationOptions result;
+ if (capacityReserved)
+ result |= CapacityReserved;
+ return result;
+ }
+
+ static QArrayData *allocate(size_t objectSize, size_t alignment,
+ size_t capacity, AllocationOptions options = Default)
+ Q_REQUIRED_RESULT;
+ static void deallocate(QArrayData *data, size_t objectSize,
+ size_t alignment);
+
+ static const QArrayData shared_null;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::AllocationOptions)
+
+template <class T>
+struct QTypedArrayData
+ : QArrayData
+{
+ typedef T *iterator;
+ typedef const T *const_iterator;
+
+ T *data() { return static_cast<T *>(QArrayData::data()); }
+ const T *data() const { return static_cast<const T *>(QArrayData::data()); }
+
+ T *begin() { return data(); }
+ T *end() { return data() + size; }
+ const T *begin() const { return data(); }
+ const T *end() const { return data() + size; }
+
+ class AlignmentDummy { QArrayData header; T data; };
+
+ static QTypedArrayData *allocate(size_t capacity,
+ AllocationOptions options = Default) Q_REQUIRED_RESULT
+ {
+ return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T),
+ Q_ALIGNOF(AlignmentDummy), capacity, options));
+ }
+
+ static void deallocate(QArrayData *data)
+ {
+ QArrayData::deallocate(data, sizeof(T), Q_ALIGNOF(AlignmentDummy));
+ }
+
+ static QTypedArrayData *fromRawData(const T *data, size_t n,
+ AllocationOptions options = Default)
+ {
+ 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 = n;
+ }
+ return result;
+ }
+
+ static QTypedArrayData *sharedNull()
+ {
+ return static_cast<QTypedArrayData *>(
+ const_cast<QArrayData *>(&QArrayData::shared_null));
+ }
+};
+
+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(type, size) { \
+ Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, \
+ (sizeof(QArrayData) + (Q_ALIGNOF(type) - 1)) \
+ & ~(Q_ALIGNOF(type) - 1) } \
+ /**/
+
+////////////////////////////////////////////////////////////////////////////////
+// Q_ARRAY_LITERAL
+
+// The idea here is to place a (read-only) copy of header and array data in an
+// mmappable portion of the executable (typically, .rodata section). This is
+// accomplished by hiding a static const instance of QStaticArrayData, which is
+// POD.
+
+#if defined(Q_COMPILER_VARIADIC_MACROS)
+#if defined(Q_COMPILER_LAMBDA)
+// Hide array inside a lambda
+#define Q_ARRAY_LITERAL(Type, ...) \
+ ([]() -> QArrayDataPointerRef<Type> { \
+ /* MSVC 2010 Doesn't support static variables in a lambda, but */ \
+ /* happily accepts them in a static function of a lambda-local */ \
+ /* struct :-) */ \
+ struct StaticWrapper { \
+ static QArrayDataPointerRef<Type> get() \
+ { \
+ Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__) \
+ return ref; \
+ } \
+ }; \
+ return StaticWrapper::get(); \
+ }()) \
+ /**/
+#elif defined(Q_CC_GNU)
+// Hide array within GCC's __extension__ {( )} block
+#define Q_ARRAY_LITERAL(Type, ...) \
+ __extension__ ({ \
+ Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__) \
+ ref; \
+ }) \
+ /**/
+#endif
+#endif // defined(Q_COMPILER_VARIADIC_MACROS)
+
+#if defined(Q_ARRAY_LITERAL)
+#define Q_ARRAY_LITERAL_IMPL(Type, ...) \
+ union { Type type_must_be_POD; } dummy; Q_UNUSED(dummy) \
+ \
+ /* Portable compile-time array size computation */ \
+ Type data[] = { __VA_ARGS__ }; Q_UNUSED(data) \
+ enum { Size = sizeof(data) / sizeof(data[0]) }; \
+ \
+ static const QStaticArrayData<Type, Size> literal = { \
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(Type, Size), { __VA_ARGS__ } }; \
+ \
+ QArrayDataPointerRef<Type> ref = \
+ { static_cast<QTypedArrayData<Type> *>( \
+ const_cast<QArrayData *>(&literal.header)) }; \
+ /**/
+#else
+// As a fallback, memory is allocated and data copied to the heap.
+
+// The fallback macro does NOT use variadic macros and does NOT support
+// variable number of arguments. It is suitable for char arrays.
+
+namespace QtPrivate {
+ template <class T, size_t N>
+ inline QArrayDataPointerRef<T> qMakeArrayLiteral(const T (&array)[N])
+ {
+ union { T type_must_be_POD; } dummy; Q_UNUSED(dummy)
+
+ QArrayDataPointerRef<T> result = { QTypedArrayData<T>::allocate(N) };
+ Q_CHECK_PTR(result.ptr);
+
+ ::memcpy(result.ptr->data(), array, N * sizeof(T));
+ result.ptr->size = N;
+
+ return result;
+ }
+}
+
+#define Q_ARRAY_LITERAL(Type, Array) \
+ QT_PREPEND_NAMESPACE(QtPrivate::qMakeArrayLiteral)<Type>( Array )
+#endif // !defined(Q_ARRAY_LITERAL)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // include guard
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
new file mode 100644
index 0000000000..1b8ed3372d
--- /dev/null
+++ b/src/corelib/tools/qarraydataops.h
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QARRAYDATAOPS_H
+#define QARRAYDATAOPS_H
+
+#include <QtCore/qarraydata.h>
+
+#include <new>
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+
+template <class T>
+struct QPodArrayOps
+ : QTypedArrayData<T>
+{
+ void copyAppend(const T *b, const T *e)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(b < e);
+ Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+
+ ::memcpy(this->end(), b, (e - b) * sizeof(T));
+ this->size += e - b;
+ }
+
+ void copyAppend(size_t n, const T &t)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(n <= this->alloc - uint(this->size));
+
+ T *iter = this->end();
+ const T *const end = iter + n;
+ for (; iter != end; ++iter)
+ ::memcpy(iter, &t, sizeof(T));
+ this->size += n;
+ }
+
+ void destroyAll() // Call from destructors, ONLY!
+ {
+ Q_ASSERT(this->ref.atomic.load() == 0);
+
+ // As this is to be called only from destructor, it doesn't need to be
+ // exception safe; size not updated.
+ }
+
+ void insert(T *where, const T *b, const T *e)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
+ Q_ASSERT(b < e);
+ Q_ASSERT(e <= where || b > this->end()); // No overlap
+ Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+
+ ::memmove(where + (e - b), where, (this->end() - where) * sizeof(T));
+ ::memcpy(where, b, (e - b) * sizeof(T));
+ this->size += (e - b);
+ }
+};
+
+template <class T>
+struct QGenericArrayOps
+ : QTypedArrayData<T>
+{
+ void copyAppend(const T *b, const T *e)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(b < e);
+ Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+
+ T *iter = this->end();
+ for (; b != e; ++iter, ++b) {
+ new (iter) T(*b);
+ ++this->size;
+ }
+ }
+
+ void copyAppend(size_t n, const T &t)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(n <= this->alloc - uint(this->size));
+
+ T *iter = this->end();
+ const T *const end = iter + n;
+ for (; iter != end; ++iter) {
+ new (iter) T(t);
+ ++this->size;
+ }
+ }
+
+ void destroyAll() // Call from destructors, ONLY
+ {
+ // 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.load() == 0);
+
+ const T *const b = this->begin();
+ const T *i = this->end();
+
+ while (i != b)
+ (--i)->~T();
+ }
+
+ void insert(T *where, const T *b, const T *e)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
+ Q_ASSERT(b < e);
+ Q_ASSERT(e <= where || b > this->end()); // No overlap
+ Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+
+ // Array may be truncated at where in case of exceptions
+
+ T *const end = this->end();
+ const T *readIter = end;
+ T *writeIter = end + (e - b);
+
+ const T *const step1End = where + qMax(e - b, 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) {
+ --e, --writeIter;
+ new (writeIter) T(*e);
+ }
+
+ destroyer.commit();
+ this->size += destroyer.end - end;
+
+ // Copy assign over existing elements
+ while (readIter != where) {
+ --readIter, --writeIter;
+ *writeIter = *readIter;
+ }
+
+ while (writeIter != where) {
+ --e, --writeIter;
+ *writeIter = *e;
+ }
+ }
+};
+
+template <class T>
+struct QMovableArrayOps
+ : QGenericArrayOps<T>
+{
+ // using QGenericArrayOps<T>::copyAppend;
+ // using QGenericArrayOps<T>::destroyAll;
+
+ void insert(T *where, const T *b, const T *e)
+ {
+ Q_ASSERT(!this->ref.isShared());
+ Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
+ Q_ASSERT(b < e);
+ Q_ASSERT(e <= where || b > this->end()); // No overlap
+ Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
+
+ // 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(begin + displace, begin, (end - begin) * sizeof(T));
+ }
+
+ void commit() { displace = 0; }
+
+ ~ReversibleDisplace()
+ {
+ if (displace)
+ ::memmove(begin, begin + displace, (end - begin) * sizeof(T));
+ }
+
+ T *const begin;
+ T *const end;
+ size_t displace;
+
+ } displace(where, this->end(), size_t(e - b));
+
+ struct CopyConstructor
+ {
+ CopyConstructor(T *w) : where(w) {}
+
+ void copy(const T *src, const T *const srcEnd)
+ {
+ n = 0;
+ for (; src != srcEnd; ++src) {
+ new (where + n) T(*src);
+ ++n;
+ }
+ n = 0;
+ }
+
+ ~CopyConstructor()
+ {
+ while (n)
+ where[--n].~T();
+ }
+
+ T *const where;
+ size_t n;
+ } copier(where);
+
+ copier.copy(b, e);
+ displace.commit();
+ this->size += (e - b);
+ }
+};
+
+template <class T, class = void>
+struct QArrayOpsSelector
+{
+ typedef QGenericArrayOps<T> Type;
+};
+
+template <class T>
+struct QArrayOpsSelector<T,
+ typename QEnableIf<
+ !QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic
+ >::Type>
+{
+ typedef QPodArrayOps<T> Type;
+};
+
+template <class T>
+struct QArrayOpsSelector<T,
+ typename QEnableIf<
+ QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic
+ >::Type>
+{
+ typedef QMovableArrayOps<T> Type;
+};
+
+} // namespace QtPrivate
+
+template <class T>
+struct QArrayDataOps
+ : QtPrivate::QArrayOpsSelector<T>::Type
+{
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // include guard
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
new file mode 100644
index 0000000000..f5ad53aa54
--- /dev/null
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QARRAYDATAPOINTER_H
+#define QARRAYDATAPOINTER_H
+
+#include <QtCore/qarraydataops.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+template <class T>
+struct QArrayDataPointer
+{
+private:
+ typedef QTypedArrayData<T> Data;
+ typedef QArrayDataOps<T> DataOps;
+
+public:
+ QArrayDataPointer()
+ : d(Data::sharedNull())
+ {
+ }
+
+ QArrayDataPointer(const QArrayDataPointer &other)
+ : d(other.d->ref.ref()
+ ? other.d
+ : other.clone(other.d->cloneFlags()))
+ {
+ }
+
+ explicit QArrayDataPointer(QTypedArrayData<T> *ptr)
+ : d(ptr)
+ {
+ Q_CHECK_PTR(ptr);
+ }
+
+ QArrayDataPointer(QArrayDataPointerRef<T> ref)
+ : d(ref.ptr)
+ {
+ }
+
+ QArrayDataPointer &operator=(const QArrayDataPointer &other)
+ {
+ QArrayDataPointer tmp(other);
+ this->swap(tmp);
+ return *this;
+ }
+
+#ifdef Q_COMPILER_RVALUE_REFS
+ QArrayDataPointer(QArrayDataPointer &&other)
+ : d(other.d)
+ {
+ other.d = Data::sharedNull();
+ }
+
+ QArrayDataPointer &operator=(QArrayDataPointer &&other)
+ {
+ this->swap(other);
+ return *this;
+ }
+#endif
+
+ DataOps &operator*() const
+ {
+ Q_ASSERT(d);
+ return *static_cast<DataOps *>(d);
+ }
+
+ DataOps *operator->() const
+ {
+ Q_ASSERT(d);
+ return static_cast<DataOps *>(d);
+ }
+
+ ~QArrayDataPointer()
+ {
+ if (!d->ref.deref()) {
+ (*this)->destroyAll();
+ Data::deallocate(d);
+ }
+ }
+
+ bool isNull() const
+ {
+ return d == Data::sharedNull();
+ }
+
+ Data *data() const
+ {
+ return d;
+ }
+
+ void setSharable(bool sharable)
+ {
+ // Can't call setSharable on static read-only data, like shared_null
+ // and the internal shared-empties.
+ if (d->alloc == 0 && d->size == 0) {
+ d = Data::allocate(0, sharable
+ ? QArrayData::Default
+ : QArrayData::Unsharable);
+ return;
+ }
+
+ detach();
+ d->ref.setSharable(sharable);
+ }
+
+ void swap(QArrayDataPointer &other)
+ {
+ qSwap(d, other.d);
+ }
+
+ void clear()
+ {
+ QArrayDataPointer tmp(d);
+ d = Data::sharedNull();
+ }
+
+ bool detach()
+ {
+ if (!d->isMutable() || d->ref.isShared()) {
+ Data *copy = clone(d->detachFlags());
+ QArrayDataPointer old(d);
+ d = copy;
+ return true;
+ }
+
+ return false;
+ }
+
+private:
+ Data *clone(QArrayData::AllocationOptions options) const Q_REQUIRED_RESULT
+ {
+ QArrayDataPointer copy(Data::allocate(d->alloc ? d->alloc : d->size,
+ options));
+ if (d->size)
+ copy->copyAppend(d->begin(), d->end());
+
+ Data *result = copy.d;
+ copy.d = Data::sharedNull();
+ return result;
+ }
+
+ Data *d;
+};
+
+template <class T>
+inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
+{
+ return lhs.data() == rhs.data();
+}
+
+template <class T>
+inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
+{
+ return lhs.data() != rhs.data();
+}
+
+template <class T>
+inline void qSwap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2)
+{
+ p1.swap(p2);
+}
+
+QT_END_NAMESPACE
+
+namespace std
+{
+ template <class T>
+ inline void swap(
+ QT_PREPEND_NAMESPACE(QArrayDataPointer)<T> &p1,
+ QT_PREPEND_NAMESPACE(QArrayDataPointer)<T> &p2)
+ {
+ p1.swap(p2);
+ }
+}
+
+QT_END_HEADER
+
+#endif // include guard
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index b6719c9536..ac936b1d0a 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -57,7 +57,7 @@
#include <string.h>
#include <stdlib.h>
-#define IS_RAW_DATA(d) ((d)->offset != 0)
+#define IS_RAW_DATA(d) ((d)->offset != sizeof(QByteArrayData))
QT_BEGIN_NAMESPACE
@@ -69,24 +69,25 @@ int qFindByteArray(
int qAllocMore(int alloc, int extra)
{
- if (alloc == 0 && extra == 0)
- return 0;
- const int page = 1 << 12;
- int nalloc;
- alloc += extra;
- if (alloc < 1<<6) {
- nalloc = (1<<3) + ((alloc >>3) << 3);
- } else {
- // don't do anything if the loop will overflow signed int.
- if (alloc >= INT_MAX/2)
- return INT_MAX;
- nalloc = (alloc < page) ? 1 << 3 : page;
- while (nalloc < alloc) {
- if (nalloc <= 0)
- return INT_MAX;
- nalloc *= 2;
- }
- }
+ Q_ASSERT(alloc >= 0 && extra >= 0);
+ Q_ASSERT(alloc < (1 << 30) - extra);
+
+ unsigned nalloc = alloc + extra;
+
+ // Round up to next power of 2
+
+ // Assuming container is growing, always overshoot
+ //--nalloc;
+
+ nalloc |= nalloc >> 1;
+ nalloc |= nalloc >> 2;
+ nalloc |= nalloc >> 4;
+ nalloc |= nalloc >> 8;
+ nalloc |= nalloc >> 16;
+ ++nalloc;
+
+ Q_ASSERT(nalloc > unsigned(alloc + extra));
+
return nalloc - extra;
}
@@ -554,7 +555,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
}
d.take(); // realloc was successful
d.reset(p);
- d->offset = 0;
+ d->offset = sizeof(QByteArrayData);
int res = ::uncompress((uchar*)d->data(), &len,
(uchar*)data+4, nbytes-4);
@@ -576,11 +577,11 @@ QByteArray qUncompress(const uchar* data, int nbytes)
d.take(); // realloc was successful
d.reset(p);
}
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = len;
d->alloc = len;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QByteArrayData);
d->data()[len] = 0;
return QByteArray(d.take(), 0, 0);
@@ -614,10 +615,10 @@ static inline char qToLower(char c)
return c;
}
-const QConstByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZER(-1),
- 0, 0, 0, { 0 } }, { 0 } };
-const QConstByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1),
- 0, 0, 0, { 0 } }, { 0 } };
+const QStaticByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC,
+ 0, 0, 0, sizeof(QByteArrayData) }, { 0 } };
+const QStaticByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC,
+ 0, 0, 0, sizeof(QByteArrayData) }, { 0 } };
/*!
\class QByteArray
@@ -904,7 +905,7 @@ QByteArray &QByteArray::operator=(const char *str)
x = const_cast<Data *>(&shared_empty.ba);
} else {
int len = qstrlen(str);
- if (d->ref != 1 || len > int(d->alloc) || (len < d->size && len < int(d->alloc) >> 1))
+ if (d->ref.isShared() || len > int(d->alloc) || (len < d->size && len < int(d->alloc) >> 1))
realloc(len);
x = d;
memcpy(x->data(), str, len + 1); // include null terminator
@@ -1289,38 +1290,16 @@ void QByteArray::chop(int n)
\sa isEmpty()
*/
-/*! \fn QByteArray::QByteArray(const char *str)
-
- Constructs a byte array initialized with the string \a str.
-
- QByteArray makes a deep copy of the string data.
-*/
-
-QByteArray::QByteArray(const char *str)
-{
- if (!str) {
- d = const_cast<Data *>(&shared_null.ba);
- } else if (!*str) {
- d = const_cast<Data *>(&shared_empty.ba);
- } else {
- int len = qstrlen(str);
- d = static_cast<Data *>(malloc(sizeof(Data) + len + 1));
- Q_CHECK_PTR(d);
- d->ref = 1;
- d->size = len;
- d->alloc = len;
- d->capacityReserved = false;
- d->offset = 0;
- memcpy(d->data(), str, len+1); // include null terminator
- }
-}
-
/*!
Constructs a byte array containing the first \a size bytes of
array \a data.
If \a data is 0, a null byte array is constructed.
+ If \a size is negative, \a data is assumed to point to a nul-terminated
+ string and its length is determined dynamically. The terminating
+ nul-character is not considered part of the byte array.
+
QByteArray makes a deep copy of the string data.
\sa fromRawData()
@@ -1330,18 +1309,22 @@ QByteArray::QByteArray(const char *data, int size)
{
if (!data) {
d = const_cast<Data *>(&shared_null.ba);
- } else if (size <= 0) {
- d = const_cast<Data *>(&shared_empty.ba);
} else {
- d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
- Q_CHECK_PTR(d);
- d->ref = 1;
- d->size = size;
- d->alloc = size;
- d->capacityReserved = false;
- d->offset = 0;
- memcpy(d->data(), data, size);
- d->data()[size] = '\0';
+ if (size < 0)
+ size = strlen(data);
+ if (!size) {
+ d = const_cast<Data *>(&shared_empty.ba);
+ } else {
+ d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
+ Q_CHECK_PTR(d);
+ d->ref.initializeOwned();
+ d->size = size;
+ d->alloc = size;
+ d->capacityReserved = false;
+ d->offset = sizeof(QByteArrayData);
+ memcpy(d->data(), data, size);
+ d->data()[size] = '\0';
+ }
}
}
@@ -1359,11 +1342,11 @@ QByteArray::QByteArray(int size, char ch)
} else {
d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = size;
d->alloc = size;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QByteArrayData);
memset(d->data(), ch, size);
d->data()[size] = '\0';
}
@@ -1379,11 +1362,11 @@ QByteArray::QByteArray(int size, Qt::Initialization)
{
d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = size;
d->alloc = size;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QByteArrayData);
d->data()[size] = '\0';
}
@@ -1405,7 +1388,7 @@ void QByteArray::resize(int size)
if (size < 0)
size = 0;
- if (d->offset && d->ref == 1 && size < d->size) {
+ if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) {
d->size = size;
return;
}
@@ -1426,15 +1409,15 @@ void QByteArray::resize(int size)
//
Data *x = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(x);
- x->ref = 1;
+ x->ref.initializeOwned();
x->size = size;
x->alloc = size;
x->capacityReserved = false;
- x->offset = 0;
+ x->offset = sizeof(QByteArrayData);
x->data()[size] = '\0';
d = x;
} else {
- if (d->ref != 1 || size > int(d->alloc)
+ if (d->ref.isShared() || size > int(d->alloc)
|| (!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
realloc(qAllocMore(size, sizeof(Data)));
if (int(d->alloc) >= size) {
@@ -1465,14 +1448,14 @@ QByteArray &QByteArray::fill(char ch, int size)
void QByteArray::realloc(int alloc)
{
- if (d->ref != 1 || d->offset) {
+ if (d->ref.isShared() || IS_RAW_DATA(d)) {
Data *x = static_cast<Data *>(malloc(sizeof(Data) + alloc + 1));
Q_CHECK_PTR(x);
- x->ref = 1;
+ x->ref.initializeOwned();
x->size = qMin(alloc, d->size);
x->alloc = alloc;
x->capacityReserved = d->capacityReserved;
- x->offset = 0;
+ x->offset = sizeof(QByteArrayData);
::memcpy(x->data(), d->data(), x->size);
x->data()[x->size] = '\0';
if (!d->ref.deref())
@@ -1482,7 +1465,7 @@ void QByteArray::realloc(int alloc)
Data *x = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc + 1));
Q_CHECK_PTR(x);
x->alloc = alloc;
- x->offset = 0;
+ x->offset = sizeof(QByteArrayData);
d = x;
}
}
@@ -1504,7 +1487,7 @@ void QByteArray::expand(int i)
QByteArray QByteArray::nulTerminated() const
{
// is this fromRawData?
- if (!d->offset)
+ if (!IS_RAW_DATA(d))
return *this; // no, then we're sure we're zero terminated
QByteArray copy(*this);
@@ -1566,7 +1549,7 @@ QByteArray &QByteArray::prepend(const char *str)
QByteArray &QByteArray::prepend(const char *str, int len)
{
if (str) {
- if (d->ref != 1 || d->size + len > int(d->alloc))
+ if (d->ref.isShared() || d->size + len > int(d->alloc))
realloc(qAllocMore(d->size + len, sizeof(Data)));
memmove(d->data()+len, d->data(), d->size);
memcpy(d->data(), str, len);
@@ -1584,7 +1567,7 @@ QByteArray &QByteArray::prepend(const char *str, int len)
QByteArray &QByteArray::prepend(char ch)
{
- if (d->ref != 1 || d->size + 1 > int(d->alloc))
+ if (d->ref.isShared() || d->size + 1 > int(d->alloc))
realloc(qAllocMore(d->size + 1, sizeof(Data)));
memmove(d->data()+1, d->data(), d->size);
d->data()[0] = ch;
@@ -1622,7 +1605,7 @@ QByteArray &QByteArray::append(const QByteArray &ba)
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
*this = ba;
} else if (ba.d != &shared_null.ba) {
- if (d->ref != 1 || d->size + ba.d->size > int(d->alloc))
+ if (d->ref.isShared() || d->size + ba.d->size > int(d->alloc))
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
d->size += ba.d->size;
@@ -1656,7 +1639,7 @@ QByteArray& QByteArray::append(const char *str)
{
if (str) {
int len = qstrlen(str);
- if (d->ref != 1 || d->size + len > int(d->alloc))
+ if (d->ref.isShared() || d->size + len > int(d->alloc))
realloc(qAllocMore(d->size + len, sizeof(Data)));
memcpy(d->data() + d->size, str, len + 1); // include null terminator
d->size += len;
@@ -1681,7 +1664,7 @@ QByteArray &QByteArray::append(const char *str, int len)
if (len < 0)
len = qstrlen(str);
if (str && len) {
- if (d->ref != 1 || d->size + len > int(d->alloc))
+ if (d->ref.isShared() || d->size + len > int(d->alloc))
realloc(qAllocMore(d->size + len, sizeof(Data)));
memcpy(d->data() + d->size, str, len); // include null terminator
d->size += len;
@@ -1698,7 +1681,7 @@ QByteArray &QByteArray::append(const char *str, int len)
QByteArray& QByteArray::append(char ch)
{
- if (d->ref != 1 || d->size + 1 > int(d->alloc))
+ if (d->ref.isShared() || d->size + 1 > int(d->alloc))
realloc(qAllocMore(d->size + 1, sizeof(Data)));
d->data()[d->size++] = ch;
d->data()[d->size] = '\0';
@@ -3889,11 +3872,11 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
} else {
x = static_cast<Data *>(malloc(sizeof(Data) + 1));
Q_CHECK_PTR(x);
- x->ref = 1;
+ x->ref.initializeOwned();
x->size = size;
x->alloc = 0;
x->capacityReserved = false;
- x->offset = data - (x->d + sizeof(qptrdiff));
+ x->offset = data - reinterpret_cast<char *>(x);
}
return QByteArray(x, 0, 0);
}
@@ -3914,14 +3897,14 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
*/
QByteArray &QByteArray::setRawData(const char *data, uint size)
{
- if (d->ref != 1 || d->alloc) {
+ if (d->ref.isShared() || d->alloc) {
*this = fromRawData(data, size);
} else {
if (data) {
d->size = size;
- d->offset = data - (d->d + sizeof(qptrdiff));
+ d->offset = data - reinterpret_cast<char *>(d);
} else {
- d->offset = 0;
+ d->offset = sizeof(QByteArrayData);
d->size = 0;
*d->data() = 0;
}
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 09c43988fd..bd3a4a8444 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -124,32 +124,31 @@ struct QByteArrayData
int size;
uint alloc : 31;
uint capacityReserved : 1;
- union {
- qptrdiff offset; // will always work as we add/subtract from a ushort ptr
- char d[sizeof(qptrdiff)];
- };
- inline char *data() { return d + sizeof(qptrdiff) + offset; }
- inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
+
+ qptrdiff offset;
+
+ inline char *data() { return reinterpret_cast<char *>(this) + offset; }
+ inline const char *data() const { return reinterpret_cast<const char *>(this) + offset; }
};
-template<int N> struct QConstByteArrayData
+template<int N> struct QStaticByteArrayData
{
- const QByteArrayData ba;
- const char data[N + 1];
+ QByteArrayData ba;
+ char data[N + 1];
};
-template<int N> struct QConstByteArrayDataPtr
+template<int N> struct QStaticByteArrayDataPtr
{
- const QConstByteArrayData<N> *ptr;
+ const QStaticByteArrayData<N> *ptr;
};
#if defined(Q_COMPILER_LAMBDA)
-# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr<sizeof(str) - 1> { \
+# define QByteArrayLiteral(str) ([]() -> QStaticByteArrayDataPtr<sizeof(str) - 1> { \
enum { Size = sizeof(str) - 1 }; \
- static const QConstByteArrayData<Size> qbytearray_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
- QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
+ static const QStaticByteArrayData<Size> qbytearray_literal = \
+ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QByteArrayData) }, str }; \
+ QStaticByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
return holder; }())
#elif defined(Q_CC_GNU)
@@ -160,9 +159,9 @@ template<int N> struct QConstByteArrayDataPtr
# define QByteArrayLiteral(str) \
__extension__ ({ \
enum { Size = sizeof(str) - 1 }; \
- static const QConstByteArrayData<Size> qbytearray_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
- QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
+ static const QStaticByteArrayData<Size> qbytearray_literal = \
+ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QByteArrayData) }, str }; \
+ QStaticByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
holder; })
#endif
@@ -180,8 +179,7 @@ private:
public:
inline QByteArray();
- QByteArray(const char *);
- QByteArray(const char *, int size);
+ QByteArray(const char *, int size = -1);
QByteArray(int size, char c);
QByteArray(int size, Qt::Initialization);
inline QByteArray(const QByteArray &);
@@ -207,10 +205,8 @@ public:
void squeeze();
#ifndef QT_NO_CAST_FROM_BYTEARRAY
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED operator const char *() const { return constData(); }
- QT_DEPRECATED operator const void *() const { return constData(); }
-#endif
+ operator const char *() const;
+ operator const void *() const;
#endif
char *data();
const char *data() const;
@@ -379,16 +375,16 @@ public:
bool isNull() const;
template <int n>
- inline QByteArray(const QConstByteArrayData<n> &dd)
+ inline QByteArray(const QStaticByteArrayData<n> &dd)
: d(const_cast<QByteArrayData *>(&dd.ba)) {}
template <int N>
- Q_DECL_CONSTEXPR inline QByteArray(QConstByteArrayDataPtr<N> dd)
+ Q_DECL_CONSTEXPR inline QByteArray(QStaticByteArrayDataPtr<N> dd)
: d(const_cast<QByteArrayData *>(&dd.ptr->ba)) {}
private:
operator QNoImplicitBoolCast() const;
- static const QConstByteArrayData<1> shared_null;
- static const QConstByteArrayData<1> shared_empty;
+ static const QStaticByteArrayData<1> shared_null;
+ static const QStaticByteArrayData<1> shared_empty;
Data *d;
QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
void realloc(int alloc);
@@ -417,6 +413,12 @@ inline char QByteArray::operator[](uint i) const
inline bool QByteArray::isEmpty() const
{ return d->size == 0; }
+#ifndef QT_NO_CAST_FROM_BYTEARRAY
+inline QByteArray::operator const char *() const
+{ return d->data(); }
+inline QByteArray::operator const void *() const
+{ return d->data(); }
+#endif
inline char *QByteArray::data()
{ detach(); return d->data(); }
inline const char *QByteArray::data() const
@@ -424,9 +426,9 @@ inline const char *QByteArray::data() const
inline const char *QByteArray::constData() const
{ return d->data(); }
inline void QByteArray::detach()
-{ if (d->ref != 1 || d->offset) realloc(d->size); }
+{ if (d->ref.isShared() || (d->offset != sizeof(QByteArrayData))) realloc(d->size); }
inline bool QByteArray::isDetached() const
-{ return d->ref == 1; }
+{ return !d->ref.isShared(); }
inline QByteArray::QByteArray(const QByteArray &a) : d(a.d)
{ d->ref.ref(); }
@@ -435,7 +437,7 @@ inline int QByteArray::capacity() const
inline void QByteArray::reserve(int asize)
{
- if (d->ref != 1 || asize > int(d->alloc))
+ if (d->ref.isShared() || asize > int(d->alloc))
realloc(asize);
if (!d->capacityReserved) {
@@ -446,11 +448,12 @@ inline void QByteArray::reserve(int asize)
inline void QByteArray::squeeze()
{
- if (d->ref > 1 || d->size < int(d->alloc))
+ if (d->ref.isShared() || d->size < int(d->alloc))
realloc(d->size);
if (d->capacityReserved) {
- // cannot set unconditionally, since d could be the shared_null/shared_empty (which is const)
+ // cannot set unconditionally, since d could be shared_null or
+ // otherwise static.
d->capacityReserved = false;
}
}
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index d5703e8b2a..897de77f2e 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -166,7 +166,7 @@ static int countBits(int hint)
const int MinNumBits = 4;
const QHashData QHashData::shared_null = {
- 0, 0, Q_REFCOUNT_INITIALIZER(-1), 0, 0, MinNumBits, 0, 0, true, false, 0
+ 0, 0, Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, MinNumBits, 0, 0, true, false, 0
};
void *QHashData::allocateNode(int nodeAlign)
@@ -196,7 +196,7 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
d = new QHashData;
d->fakeNext = 0;
d->buckets = 0;
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = size;
d->nodeSize = nodeSize;
d->userNumBits = userNumBits;
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 9e4007c26e..91d015c394 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -288,8 +288,8 @@ public:
void reserve(int size);
inline void squeeze() { reserve(1); }
- inline void detach() { if (d->ref != 1) detach_helper(); }
- inline bool isDetached() const { return d->ref == 1; }
+ inline void detach() { if (d->ref.isShared()) detach_helper(); }
+ inline bool isDetached() const { return !d->ref.isShared(); }
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QHashData::shared_null) d->sharable = sharable; }
inline bool isSharedWith(const QHash<Key, T> &other) const { return d == other.d; }
diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp
index b31ef3e5e9..6e66f804c0 100644
--- a/src/corelib/tools/qlinkedlist.cpp
+++ b/src/corelib/tools/qlinkedlist.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
const QLinkedListData QLinkedListData::shared_null = {
const_cast<QLinkedListData *>(&QLinkedListData::shared_null),
const_cast<QLinkedListData *>(&QLinkedListData::shared_null),
- Q_REFCOUNT_INITIALIZER(-1), 0, true
+ Q_REFCOUNT_INITIALIZE_STATIC, 0, true
};
/*! \class QLinkedList
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index 2e6d05ac35..28f190c7fa 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -94,8 +94,8 @@ public:
inline int size() const { return d->size; }
inline void detach()
- { if (d->ref != 1) detach_helper(); }
- inline bool isDetached() const { return d->ref == 1; }
+ { if (d->ref.isShared()) detach_helper(); }
+ inline bool isDetached() const { return !d->ref.isShared(); }
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QLinkedListData::shared_null) d->sharable = sharable; }
inline bool isSharedWith(const QLinkedList<T> &other) const { return d == other.d; }
@@ -241,8 +241,6 @@ private:
template <typename T>
inline QLinkedList<T>::~QLinkedList()
{
- if (!d)
- return;
if (!d->ref.deref())
free(d);
}
@@ -252,7 +250,7 @@ void QLinkedList<T>::detach_helper()
{
union { QLinkedListData *d; Node *e; } x;
x.d = new QLinkedListData;
- x.d->ref = 1;
+ x.d->ref.initializeOwned();
x.d->size = d->size;
x.d->sharable = true;
Node *original = e->n;
@@ -265,6 +263,7 @@ void QLinkedList<T>::detach_helper()
copy = copy->n;
} QT_CATCH(...) {
copy->n = x.e;
+ Q_ASSERT(!x.d->ref.deref()); // Don't trigger assert in free
free(x.d);
QT_RETHROW;
}
@@ -281,14 +280,13 @@ void QLinkedList<T>::free(QLinkedListData *x)
{
Node *y = reinterpret_cast<Node*>(x);
Node *i = y->n;
- if (x->ref == 0) {
- while(i != y) {
- Node *n = i;
- i = i->n;
- delete n;
- }
- delete x;
+ Q_ASSERT(x->ref.atomic.load() == 0);
+ while (i != y) {
+ Node *n = i;
+ i = i->n;
+ delete n;
}
+ delete x;
}
template <typename T>
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 263045a25d..9ee4c0a797 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
the number of elements in the list.
*/
-const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZER(-1), 0, 0, 0, true, { 0 } };
+const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } };
static int grow(int size)
{
@@ -87,8 +87,7 @@ QListData::Data *QListData::detach_grow(int *idx, int num)
Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *)));
Q_CHECK_PTR(t);
- t->ref = 1;
- t->sharable = true;
+ t->ref.initializeOwned();
t->alloc = alloc;
// The space reservation algorithm's optimization is biased towards appending:
// Something which looks like an append will put the data at the beginning,
@@ -129,8 +128,7 @@ QListData::Data *QListData::detach(int alloc)
Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *)));
Q_CHECK_PTR(t);
- t->ref = 1;
- t->sharable = true;
+ t->ref.initializeOwned();
t->alloc = alloc;
if (!alloc) {
t->begin = 0;
@@ -146,7 +144,7 @@ QListData::Data *QListData::detach(int alloc)
void QListData::realloc(int alloc)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *)));
Q_CHECK_PTR(x);
@@ -159,7 +157,7 @@ void QListData::realloc(int alloc)
// ensures that enough space is available to append n elements
void **QListData::append(int n)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
int e = d->end;
if (e + n > d->alloc) {
int b = d->begin;
@@ -190,7 +188,7 @@ void **QListData::append(const QListData& l)
void **QListData::prepend()
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
if (d->begin == 0) {
if (d->end >= d->alloc / 3)
realloc(grow(d->alloc + 1));
@@ -208,7 +206,7 @@ void **QListData::prepend()
void **QListData::insert(int i)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
if (i <= 0)
return prepend();
int size = d->end - d->begin;
@@ -247,7 +245,7 @@ void **QListData::insert(int i)
void QListData::remove(int i)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
i += d->begin;
if (i - d->begin < d->end - i) {
if (int offset = i - d->begin)
@@ -262,7 +260,7 @@ void QListData::remove(int i)
void QListData::remove(int i, int n)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
i += d->begin;
int middle = i + n/2;
if (middle - d->begin < d->end - middle) {
@@ -278,7 +276,7 @@ void QListData::remove(int i, int n)
void QListData::move(int from, int to)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
if (from == to)
return;
@@ -318,7 +316,7 @@ void QListData::move(int from, int to)
void **QListData::erase(void **xi)
{
- Q_ASSERT(d->ref == 1);
+ Q_ASSERT(!d->ref.isShared());
int i = xi - (d->array + d->begin);
remove(i);
return d->array + d->begin + i;
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index bf6933732c..bc3350f42b 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -71,7 +71,6 @@ struct Q_CORE_EXPORT QListData {
struct Data {
QtPrivate::RefCount ref;
int alloc, begin, end;
- uint sharable : 1;
void *array[1];
};
enum { DataHeaderSize = sizeof(Data) - sizeof(void *) };
@@ -114,7 +113,7 @@ class QList
public:
inline QList() : d(const_cast<QListData::Data *>(&QListData::shared_null)) { }
- inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+ QList(const QList<T> &l);
~QList();
QList<T> &operator=(const QList<T> &l);
#ifdef Q_COMPILER_RVALUE_REFS
@@ -132,17 +131,25 @@ public:
inline int size() const { return p.size(); }
- inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline void detach() { if (d->ref.isShared()) detach_helper(); }
inline void detachShared()
{
// The "this->" qualification is needed for GCCE.
- if (d->ref != 1 && this->d != &QListData::shared_null)
+ if (d->ref.isShared() && this->d != &QListData::shared_null)
detach_helper();
}
- inline bool isDetached() const { return d->ref == 1; }
- inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QListData::shared_null) d->sharable = sharable; }
+ inline bool isDetached() const { return !d->ref.isShared(); }
+ inline void setSharable(bool sharable)
+ {
+ if (sharable == d->ref.isSharable())
+ return;
+ if (!sharable)
+ detach();
+ if (d != &QListData::shared_null)
+ d->ref.setSharable(sharable);
+ }
inline bool isSharedWith(const QList<T> &other) const { return d == other.d; }
inline bool isEmpty() const { return p.isEmpty(); }
@@ -419,13 +426,8 @@ template <typename T>
Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
{
if (d != l.d) {
- QListData::Data *o = l.d;
- o->ref.ref();
- if (!d->ref.deref())
- dealloc(d);
- d = o;
- if (!d->sharable)
- detach_helper();
+ QList<T> tmp(l);
+ tmp.swap(*this);
}
return *this;
}
@@ -478,7 +480,7 @@ template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
{
if (d->alloc < alloc) {
- if (d->ref != 1)
+ if (d->ref.isShared())
detach_helper(alloc);
else
p.realloc(alloc);
@@ -488,7 +490,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
{
- if (d->ref != 1) {
+ if (d->ref.isShared()) {
Node *n = detach_helper_grow(INT_MAX, 1);
QT_TRY {
node_construct(n, t);
@@ -522,7 +524,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
template <typename T>
inline void QList<T>::prepend(const T &t)
{
- if (d->ref != 1) {
+ if (d->ref.isShared()) {
Node *n = detach_helper_grow(0, 1);
QT_TRY {
node_construct(n, t);
@@ -556,7 +558,7 @@ inline void QList<T>::prepend(const T &t)
template <typename T>
inline void QList<T>::insert(int i, const T &t)
{
- if (d->ref != 1) {
+ if (d->ref.isShared()) {
Node *n = detach_helper_grow(i, 1);
QT_TRY {
node_construct(n, t);
@@ -708,6 +710,28 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
}
template <typename T>
+Q_OUTOFLINE_TEMPLATE QList<T>::QList(const QList<T> &l)
+ : d(l.d)
+{
+ if (!d->ref.ref()) {
+ p.detach(d->alloc);
+
+ struct Cleanup
+ {
+ Cleanup(QListData::Data *d) : d_(d) {}
+ ~Cleanup() { if (d_) qFree(d_); }
+
+ QListData::Data *d_;
+ } tryCatch(d);
+
+ node_copy(reinterpret_cast<Node *>(p.begin()),
+ reinterpret_cast<Node *>(p.end()),
+ reinterpret_cast<Node *>(l.p.begin()));
+ tryCatch.d_ = 0;
+ }
+}
+
+template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T>::~QList()
{
if (!d->ref.deref())
@@ -802,7 +826,7 @@ Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
if (isEmpty()) {
*this = l;
} else {
- Node *n = (d->ref != 1)
+ Node *n = (d->ref.isShared())
? detach_helper_grow(INT_MAX, l.size())
: reinterpret_cast<Node *>(p.append(l.p));
QT_TRY {
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 103d074941..c922d7aab0 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
const QMapData QMapData::shared_null = {
const_cast<QMapData *>(&shared_null),
{ const_cast<QMapData *>(&shared_null), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- Q_REFCOUNT_INITIALIZER(-1), 0, 0, 0, false, true, false, 0
+ Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, false, true, false, 0
};
QMapData *QMapData::createData(int alignment)
@@ -63,7 +63,7 @@ QMapData *QMapData::createData(int alignment)
Node *e = reinterpret_cast<Node *>(d);
e->backward = e;
e->forward[0] = e;
- d->ref = 1;
+ d->ref.initializeOwned();
d->topLevel = 0;
d->size = 0;
d->randomBits = 0;
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 515b60bea6..dc358a8106 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -179,7 +179,7 @@ public:
inline QMap() : d(const_cast<QMapData *>(&QMapData::shared_null)) { }
inline QMap(const QMap<Key, T> &other) : d(other.d)
{ d->ref.ref(); if (!d->sharable) detach(); }
- inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); }
+ inline ~QMap() { if (!d->ref.deref()) freeData(d); }
QMap<Key, T> &operator=(const QMap<Key, T> &other);
#ifdef Q_COMPILER_RVALUE_REFS
@@ -199,8 +199,8 @@ public:
inline bool isEmpty() const { return d->size == 0; }
- inline void detach() { if (d->ref != 1) detach_helper(); }
- inline bool isDetached() const { return d->ref == 1; }
+ inline void detach() { if (d->ref.isShared()) detach_helper(); }
+ inline bool isDetached() const { return !d->ref.isShared(); }
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QMapData::shared_null) d->sharable = sharable; }
inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
inline void setInsertInOrder(bool ordered) { if (ordered) detach(); if (d != &QMapData::shared_null) d->insertInOrder = ordered; }
diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h
index bc673214fa..16b1d339b3 100644
--- a/src/corelib/tools/qrefcount.h
+++ b/src/corelib/tools/qrefcount.h
@@ -55,37 +55,61 @@ namespace QtPrivate
class RefCount
{
public:
- inline void ref() {
- if (atomic.load() > 0)
+ inline bool ref() {
+ int count = atomic.load();
+ if (count == 0) // !isSharable
+ return false;
+ if (count != -1) // !isStatic
atomic.ref();
+ return true;
}
inline bool deref() {
- if (atomic.load() <= 0)
+ int count = atomic.load();
+ if (count == 0) // !isSharable
+ return false;
+ if (count == -1) // isStatic
return true;
return atomic.deref();
}
- inline bool operator==(int value) const
- { return atomic.load() == value; }
- inline bool operator!=(int value) const
- { return atomic.load() != value; }
- inline bool operator!() const
- { return !atomic.load(); }
- inline operator int() const
- { return atomic.load(); }
- inline RefCount &operator=(int value)
- { atomic.store(value); return *this; }
- inline RefCount &operator=(const RefCount &other)
- { atomic.store(other.atomic.load()); return *this; }
+ bool setSharable(bool sharable)
+ {
+ Q_ASSERT(!isShared());
+ if (sharable)
+ return atomic.testAndSetRelaxed(0, 1);
+ else
+ return atomic.testAndSetRelaxed(1, 0);
+ }
+
+ bool isStatic() const
+ {
+ // Persistent object, never deleted
+ return atomic.load() == -1;
+ }
+
+ bool isSharable() const
+ {
+ // Sharable === Shared ownership.
+ return atomic.load() != 0;
+ }
+
+ bool isShared() const
+ {
+ int count = atomic.load();
+ return (count != 1) && (count != 0);
+ }
+
+ void initializeOwned() { atomic.store(1); }
+ void initializeUnsharable() { atomic.store(0); }
QBasicAtomicInt atomic;
};
-#define Q_REFCOUNT_INITIALIZER(a) { Q_BASIC_ATOMIC_INITIALIZER(a) }
-
}
+#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index 3ca83c9e27..57cb29035b 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -239,8 +239,6 @@ Q_DECLARE_TYPEINFO(QRegularExpressionMatchIterator, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QRegularExpression)
-
QT_END_HEADER
#endif // QT_NO_REGEXP
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 77c3d1e2cb..58c62f0a3e 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -1380,47 +1380,14 @@ Q_GLOBAL_STATIC(KnownPointers, knownPointers)
QT_BEGIN_NAMESPACE
namespace QtSharedPointer {
- Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *);
- Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *);
Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck();
}
/*!
\internal
*/
-void QtSharedPointer::internalSafetyCheckAdd(const volatile void *)
+void QtSharedPointer::internalSafetyCheckAdd(const void *d_ptr, const volatile void *ptr)
{
- // Qt 4.5 compatibility
- // this function is broken by design, so it was replaced with internalSafetyCheckAdd2
- //
- // it's broken because we tracked the pointers added and
- // removed from QSharedPointer, converted to void*.
- // That is, this is supposed to track the "top-of-object" pointer in
- // case of multiple inheritance.
- //
- // However, it doesn't work well in some compilers:
- // if you create an object with a class of type A and the last reference
- // is dropped of type B, then the value passed to internalSafetyCheckRemove could
- // be different than was added. That would leave dangling addresses.
- //
- // So instead, we track the pointer by the d-pointer instead.
-}
-
-/*!
- \internal
-*/
-void QtSharedPointer::internalSafetyCheckRemove(const volatile void *)
-{
- // Qt 4.5 compatibility
- // see comments above
-}
-
-/*!
- \internal
-*/
-void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr)
-{
- // see comments above for the rationale for this function
KnownPointers *const kp = knownPointers();
if (!kp)
return; // end-game: the application is being destroyed already
@@ -1453,7 +1420,7 @@ void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile
/*!
\internal
*/
-void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr)
+void QtSharedPointer::internalSafetyCheckRemove(const void *d_ptr)
{
KnownPointers *const kp = knownPointers();
if (!kp)
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 58010dd8d9..81ce17889e 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -105,8 +105,8 @@ namespace QtSharedPointer {
template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
// used in debug mode to verify the reuse of pointers
- Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *);
- Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *);
+ Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
+ Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
template <class T, typename Klass, typename RetVal>
inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
@@ -247,7 +247,7 @@ namespace QtSharedPointer {
}
static void safetyCheckDeleter(ExternalRefCountData *self)
{
- internalSafetyCheckRemove2(self);
+ internalSafetyCheckRemove(self);
deleter(self);
}
@@ -290,7 +290,7 @@ namespace QtSharedPointer {
}
static void safetyCheckDeleter(ExternalRefCountData *self)
{
- internalSafetyCheckRemove2(self);
+ internalSafetyCheckRemove(self);
deleter(self);
}
@@ -374,7 +374,7 @@ namespace QtSharedPointer {
Basic<T>::internalConstruct(ptr);
if (ptr) d->setQObjectShared(ptr, true);
#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
- if (ptr) internalSafetyCheckAdd2(d, ptr);
+ if (ptr) internalSafetyCheckAdd(d, ptr);
#endif
}
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 083abcbaad..878403fe75 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -41,6 +41,7 @@
#include "qstringlist.h"
#include "qregexp.h"
+#include "qregularexpression.h"
#include "qunicodetables_p.h"
#ifndef QT_NO_TEXTCODEC
#include <qtextcodec.h>
@@ -94,6 +95,8 @@
#define ULLONG_MAX quint64_C(18446744073709551615)
#endif
+#define IS_RAW_DATA(d) ((d)->offset != sizeof(QStringData))
+
QT_BEGIN_NAMESPACE
#ifdef QT_USE_ICU
@@ -793,8 +796,8 @@ const QString::Null QString::null = { };
\sa split()
*/
-const QConstStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
-const QConstStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
+const QStaticStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } };
+const QStaticStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } };
int QString::grow(int size)
{
@@ -1015,63 +1018,44 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
Constructs a string initialized with the first \a size characters
of the QChar array \a unicode.
+ If \a unicode is 0, a null string is constructed.
+
+ If \a size is negative, \a unicode is assumed to point to a nul-terminated
+ array and its length is determined dynamically. The terminating
+ nul-character is not considered part of the string.
+
QString makes a deep copy of the string data. The unicode data is copied as
is and the Byte Order Mark is preserved if present.
+
+ \sa fromRawData()
*/
QString::QString(const QChar *unicode, int size)
{
if (!unicode) {
d = const_cast<Data *>(&shared_null.str);
- } else if (size <= 0) {
- d = const_cast<Data *>(&shared_empty.str);
} else {
- d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
- Q_CHECK_PTR(d);
- d->ref = 1;
- d->size = size;
- d->alloc = (uint) size;
- d->capacityReserved = false;
- d->offset = 0;
- memcpy(d->data(), unicode, size * sizeof(QChar));
- d->data()[size] = '\0';
+ if (size < 0) {
+ size = 0;
+ while (unicode[size] != 0)
+ ++size;
+ }
+ if (!size) {
+ d = const_cast<Data *>(&shared_empty.str);
+ } else {
+ d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
+ Q_CHECK_PTR(d);
+ d->ref.initializeOwned();
+ d->size = size;
+ d->alloc = (uint) size;
+ d->capacityReserved = false;
+ d->offset = sizeof(QStringData);
+ memcpy(d->data(), unicode, size * sizeof(QChar));
+ d->data()[size] = '\0';
+ }
}
}
/*!
- \since 4.7
-
- Constructs a string initialized with the characters of the QChar array
- \a unicode, which must be terminated with a 0.
-
- QString makes a deep copy of the string data. The unicode data is copied as
- is and the Byte Order Mark is preserved if present.
-*/
-QString::QString(const QChar *unicode)
-{
- if (!unicode) {
- d = const_cast<Data *>(&shared_null.str);
- } else {
- int size = 0;
- while (unicode[size] != 0)
- ++size;
- if (!size) {
- d = const_cast<Data *>(&shared_empty.str);
- } else {
- d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
- Q_CHECK_PTR(d);
- d->ref = 1;
- d->size = size;
- d->alloc = (uint) size;
- d->capacityReserved = false;
- d->offset = 0;
- memcpy(d->data(), unicode, size * sizeof(QChar));
- d->data()[size] = '\0';
- }
- }
-}
-
-
-/*!
Constructs a string of the given \a size with every character set
to \a ch.
@@ -1084,11 +1068,11 @@ QString::QString(int size, QChar ch)
} else {
d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QStringData);
d->data()[size] = '\0';
ushort *i = d->data() + size;
ushort *b = d->data();
@@ -1108,11 +1092,11 @@ QString::QString(int size, Qt::Initialization)
{
d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QStringData);
d->data()[size] = '\0';
}
@@ -1130,11 +1114,11 @@ QString::QString(QChar ch)
{
d = (Data *) ::malloc(sizeof(Data) + 2*sizeof(QChar));
Q_CHECK_PTR(d);
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = 1;
d->alloc = 1;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QStringData);
d->data()[0] = ch.unicode();
d->data()[1] = '\0';
}
@@ -1232,7 +1216,7 @@ void QString::resize(int size)
if (size < 0)
size = 0;
- if (d->offset && d->ref == 1 && size < d->size) {
+ if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) {
d->size = size;
return;
}
@@ -1243,7 +1227,7 @@ void QString::resize(int size)
QString::free(d);
d = x;
} else {
- if (d->ref != 1 || size > int(d->alloc) ||
+ if (d->ref.isShared() || size > int(d->alloc) ||
(!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
realloc(grow(size));
if (int(d->alloc) >= size) {
@@ -1306,14 +1290,14 @@ void QString::resize(int size)
// ### Qt 5: rename reallocData() to avoid confusion. 197625
void QString::realloc(int alloc)
{
- if (d->ref != 1 || d->offset) {
+ if (d->ref.isShared() || IS_RAW_DATA(d)) {
Data *x = static_cast<Data *>(::malloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
Q_CHECK_PTR(x);
- x->ref = 1;
+ x->ref.initializeOwned();
x->size = qMin(alloc, d->size);
x->alloc = (uint) alloc;
x->capacityReserved = d->capacityReserved;
- x->offset =0;
+ x->offset = sizeof(QStringData);
::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
x->data()[x->size] = 0;
if (!d->ref.deref())
@@ -1324,7 +1308,7 @@ void QString::realloc(int alloc)
Q_CHECK_PTR(p);
d = p;
d->alloc = alloc;
- d->offset = 0;
+ d->offset = sizeof(QStringData);
}
}
@@ -1536,7 +1520,7 @@ QString &QString::append(const QString &str)
if (d == &shared_null.str) {
operator=(str);
} else {
- if (d->ref != 1 || d->size + str.d->size > int(d->alloc))
+ if (d->ref.isShared() || d->size + str.d->size > int(d->alloc))
realloc(grow(d->size + str.d->size));
memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
d->size += str.d->size;
@@ -1556,7 +1540,7 @@ QString &QString::append(const QLatin1String &str)
const uchar *s = (const uchar *)str.latin1();
if (s) {
int len = str.size();
- if (d->ref != 1 || d->size + len > int(d->alloc))
+ if (d->ref.isShared() || d->size + len > int(d->alloc))
realloc(grow(d->size + len));
ushort *i = d->data() + d->size;
while ((*i++ = *s++))
@@ -1599,7 +1583,7 @@ QString &QString::append(const QLatin1String &str)
*/
QString &QString::append(QChar ch)
{
- if (d->ref != 1 || d->size + 1 > int(d->alloc))
+ if (d->ref.isShared() || d->size + 1 > int(d->alloc))
realloc(grow(d->size + 1));
d->data()[d->size++] = ch.unicode();
d->data()[d->size] = '\0';
@@ -1758,6 +1742,18 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
*/
/*!
+ \fn QString &QString::remove(const QRegularExpression &re)
+ \since 5.0
+
+ Removes every occurrence of the regular expression \a re in the
+ string, and returns a reference to the string. For example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 96
+
+ \sa indexOf(), lastIndexOf(), replace()
+*/
+
+/*!
\fn QString &QString::replace(int position, int n, const QString &after)
Replaces \a n characters beginning at index \a position with
@@ -2940,6 +2936,138 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
}
#endif
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \overload replace()
+ \since 5.0
+
+ Replaces every occurrence of the regular expression \a re in the
+ string with \a after. Returns a reference to the string. For
+ example:
+
+ \snippet doc/src/snippets/qstring/main.cpp 87
+
+ For regular expressions containing capturing groups,
+ occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are replaced
+ with the string captured by the corresponding capturing group.
+
+ \snippet doc/src/snippets/qstring/main.cpp 88
+
+ \sa indexOf(), lastIndexOf(), remove(), QRegularExpression, QRegularExpressionMatch
+*/
+QString &QString::replace(const QRegularExpression &re, const QString &after)
+{
+ if (!re.isValid()) {
+ qWarning("QString::replace: invalid QRegularExpresssion object");
+ return *this;
+ }
+
+ const QString copy(*this);
+ QRegularExpressionMatchIterator iterator = re.globalMatch(copy);
+ if (!iterator.hasNext()) // no matches at all
+ return *this;
+
+ realloc();
+
+ int numCaptures = re.captureCount();
+
+ // 1. build the backreferences vector, holding where the backreferences
+ // are in the replacement string
+ QVector<QStringCapture> backReferences;
+ const int al = after.length();
+ const QChar *ac = after.unicode();
+
+ for (int i = 0; i < al - 1; i++) {
+ if (ac[i] == QLatin1Char('\\')) {
+ int no = ac[i + 1].digitValue();
+ if (no > 0 && no <= numCaptures) {
+ QStringCapture backReference;
+ backReference.pos = i;
+ backReference.len = 2;
+
+ if (i < al - 2) {
+ int secondDigit = ac[i + 2].digitValue();
+ if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) {
+ no = (no * 10) + secondDigit;
+ ++backReference.len;
+ }
+ }
+
+ backReference.no = no;
+ backReferences.append(backReference);
+ }
+ }
+ }
+
+ // 2. iterate on the matches. For every match, copy in chunks
+ // - the part before the match
+ // - the after string, with the proper replacements for the backreferences
+
+ int newLength = 0; // length of the new string, with all the replacements
+ int lastEnd = 0;
+ QVector<QStringRef> chunks;
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ int len;
+ // add the part before the match
+ len = match.capturedStart() - lastEnd;
+ if (len > 0) {
+ chunks << copy.midRef(lastEnd, len);
+ newLength += len;
+ }
+
+ lastEnd = 0;
+ // add the after string, with replacements for the backreferences
+ foreach (const QStringCapture &backReference, backReferences) {
+ // part of "after" before the backreference
+ len = backReference.pos - lastEnd;
+ if (len > 0) {
+ chunks << after.midRef(lastEnd, len);
+ newLength += len;
+ }
+
+ // backreference itself
+ len = match.capturedLength(backReference.no);
+ if (len > 0) {
+ chunks << copy.midRef(match.capturedStart(backReference.no), len);
+ newLength += len;
+ }
+
+ lastEnd = backReference.pos + backReference.len;
+ }
+
+ // add the last part of the after string
+ len = after.length() - lastEnd;
+ if (len > 0) {
+ chunks << after.midRef(lastEnd, len);
+ newLength += len;
+ }
+
+ lastEnd = match.capturedEnd();
+ }
+
+ // 3. trailing string after the last match
+ if (copy.length() > lastEnd) {
+ chunks << copy.midRef(lastEnd);
+ newLength += copy.length() - lastEnd;
+ }
+
+ // 4. assemble the chunks together
+ resize(newLength);
+ int i = 0;
+ QChar *uc = data();
+ foreach (const QStringRef &chunk, chunks) {
+ int len = chunk.length();
+ memcpy(uc + i, chunk.unicode(), len * sizeof(QChar));
+ i += len;
+ }
+
+ return *this;
+}
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
+
/*!
Returns the number of (potentially overlapping) occurrences of
the string \a str in this string.
@@ -3139,6 +3267,118 @@ int QString::count(const QRegExp& rx) const
}
#endif // QT_NO_REGEXP
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \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 doc/src/snippets/qstring/main.cpp 93
+*/
+int QString::indexOf(const QRegularExpression& re, int from) const
+{
+ if (!re.isValid()) {
+ qWarning("QString::indexOf: invalid QRegularExpresssion object");
+ return -1;
+ }
+
+ QRegularExpressionMatch match = re.match(*this, from);
+ if (match.hasMatch())
+ return match.capturedStart();
+
+ return -1;
+}
+
+/*!
+ \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 doc/src/snippets/qstring/main.cpp 94
+*/
+int QString::lastIndexOf(const QRegularExpression &re, int from) const
+{
+ if (!re.isValid()) {
+ qWarning("QString::lastIndexOf: invalid QRegularExpresssion object");
+ return -1;
+ }
+
+ int endpos = (from < 0) ? (size() + from + 1) : (from + 1);
+
+ QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
+ int lastIndex = -1;
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ int start = match.capturedStart();
+ if (start < endpos)
+ lastIndex = start;
+ else
+ break;
+ }
+
+ return lastIndex;
+}
+
+/*! \overload contains()
+ \since 5.0
+
+ Returns true if the regular expression \a re matches somewhere in
+ this string; otherwise returns false.
+*/
+bool QString::contains(const QRegularExpression &re) const
+{
+ if (!re.isValid()) {
+ qWarning("QString::contains: invalid QRegularExpresssion object");
+ return false;
+ }
+ QRegularExpressionMatch match = re.match(*this);
+ return match.hasMatch();
+}
+
+/*!
+ \overload count()
+ \since 5.0
+
+ Returns the number of times the regular expression \a re matches
+ in the string.
+
+ This function counts overlapping matches, so in the example
+ below, there are four instances of "ana" or "ama":
+
+ \snippet doc/src/snippets/qstring/main.cpp 95
+*/
+int QString::count(const QRegularExpression &re) const
+{
+ if (!re.isValid()) {
+ qWarning("QString::count: invalid QRegularExpresssion object");
+ return 0;
+ }
+ int count = 0;
+ int index = -1;
+ int len = length();
+ while (index < len - 1) {
+ QRegularExpressionMatch match = re.match(*this, index + 1);
+ if (!match.hasMatch())
+ break;
+ index = match.capturedStart();
+ count++;
+ }
+ return count;
+}
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
+
/*! \fn int QString::count() const
\overload count()
@@ -3266,6 +3506,49 @@ public:
QString string;
};
+static QString extractSections(const QList<qt_section_chunk> &sections,
+ int start,
+ int end,
+ QString::SectionFlags flags)
+{
+ if (start < 0)
+ start += sections.count();
+ if (end < 0)
+ end += sections.count();
+
+ QString ret;
+ int x = 0;
+ int first_i = start, last_i = end;
+ for (int i = 0; x <= end && i < sections.size(); ++i) {
+ const qt_section_chunk &section = sections.at(i);
+ const bool empty = (section.length == section.string.length());
+ if (x >= start) {
+ if (x == start)
+ first_i = i;
+ if (x == end)
+ last_i = i;
+ if (x != start)
+ ret += section.string;
+ else
+ ret += section.string.mid(section.length);
+ }
+ if (!empty || !(flags & QString::SectionSkipEmpty))
+ x++;
+ }
+
+ if ((flags & QString::SectionIncludeLeadingSep) && first_i < sections.size()) {
+ const qt_section_chunk &section = sections.at(first_i);
+ ret.prepend(section.string.left(section.length));
+ }
+
+ if ((flags & QString::SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
+ const qt_section_chunk &section = sections.at(last_i+1);
+ ret += section.string.left(section.length);
+ }
+
+ return ret;
+}
+
/*!
\overload section()
@@ -3299,41 +3582,57 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
}
sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
- if(start < 0)
- start += sections.count();
- if(end < 0)
- end += sections.count();
+ return extractSections(sections, start, end, flags);
+}
+#endif
- QString ret;
- int x = 0;
- int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sections.size(); ++i) {
- const qt_section_chunk &section = sections.at(i);
- const bool empty = (section.length == section.string.length());
- if (x >= start) {
- if(x == start)
- first_i = i;
- if(x == end)
- last_i = i;
- if(x != start)
- ret += section.string;
- else
- ret += section.string.mid(section.length);
- }
- if (!empty || !(flags & SectionSkipEmpty))
- x++;
- }
- if((flags & SectionIncludeLeadingSep) && first_i < sections.size()) {
- const qt_section_chunk &section = sections.at(first_i);
- ret.prepend(section.string.left(section.length));
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \overload section()
+ \since 5.0
+
+ This string is treated as a sequence of fields separated by the
+ regular expression, \a re.
+
+ \snippet doc/src/snippets/qstring/main.cpp 89
+
+ \warning Using this QRegularExpression version is much more expensive than
+ the overloaded string and character versions.
+
+ \sa split() simplified()
+*/
+QString QString::section(const QRegularExpression &re, int start, int end, SectionFlags flags) const
+{
+ if (!re.isValid()) {
+ qWarning("QString::section: invalid QRegularExpression object");
+ return QString();
}
- if((flags & SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
- const qt_section_chunk &section = sections.at(last_i+1);
- ret += section.string.left(section.length);
+
+ const QChar *uc = unicode();
+ if (!uc)
+ return QString();
+
+ QRegularExpression sep(re);
+ if (flags & SectionCaseInsensitiveSeps)
+ sep.setPatternOptions(sep.patternOptions() | QRegularExpression::CaseInsensitiveOption);
+
+ QList<qt_section_chunk> sections;
+ int n = length(), m = 0, last_m = 0, last_len = 0;
+ QRegularExpressionMatchIterator iterator = sep.globalMatch(*this);
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ m = match.capturedStart();
+ sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m)));
+ last_m = m;
+ last_len = match.capturedLength();
}
- return ret;
+ sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m)));
+
+ return extractSections(sections, start, end, flags);
}
-#endif
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
/*!
Returns a substring that contains the \a n leftmost characters
@@ -3390,15 +3689,17 @@ QString QString::right(int n) const
QString QString::mid(int position, int n) const
{
- if (d == &shared_null.str || position > d->size)
+ if (position > d->size)
return QString();
- if (n < 0)
- n = d->size - position;
if (position < 0) {
+ if (n < 0 || n + position >= d->size)
+ return *this;
+ if (n + position <= 0)
+ return QString();
+
n += position;
position = 0;
- }
- if (n + position > d->size)
+ } else if (n < 0 || n > d->size - position)
n = d->size - position;
if (position == 0 && n == d->size)
return *this;
@@ -3753,11 +4054,11 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
size = qstrlen(str);
d = static_cast<Data *>(::malloc(sizeof(Data) + (size+1) * sizeof(QChar)));
Q_CHECK_PTR(d);
- d->ref = 1;
+ d->ref.initializeOwned();
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
- d->offset = 0;
+ d->offset = sizeof(QStringData);
d->data()[size] = '\0';
ushort *dst = d->data();
/* SIMD:
@@ -4765,7 +5066,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
const ushort *QString::utf16() const
{
- if (d->offset)
+ if (IS_RAW_DATA(d))
const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings
return d->data();
}
@@ -6092,6 +6393,62 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
}
#endif
+#ifndef QT_NO_REGEXP
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \overload
+ \since 5.0
+
+ Splits the string into substrings wherever the regular expression
+ \a re matches, and returns the list of those strings. If \a re
+ does not match anywhere in the string, split() returns a
+ single-element list containing this string.
+
+ Here's an example where we extract the words in a sentence
+ using one or more whitespace characters as the separator:
+
+ \snippet doc/src/snippets/qstring/main.cpp 90
+
+ Here's a similar example, but this time we use any sequence of
+ non-word characters as the separator:
+
+ \snippet doc/src/snippets/qstring/main.cpp 91
+
+ Here's a third example where we use a zero-length assertion,
+ \bold{\\b} (word boundary), to split the string into an
+ alternating sequence of non-word and word tokens:
+
+ \snippet doc/src/snippets/qstring/main.cpp 92
+
+ \sa QStringList::join(), section()
+*/
+QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior) const
+{
+ QStringList list;
+ if (!re.isValid()) {
+ qWarning("QString::split: invalid QRegularExpression object");
+ return list;
+ }
+
+ int start = 0;
+ int end = 0;
+ QRegularExpressionMatchIterator iterator = re.globalMatch(*this);
+ while (iterator.hasNext()) {
+ QRegularExpressionMatch match = iterator.next();
+ end = match.capturedStart();
+ if (start != end || behavior == KeepEmptyParts)
+ list.append(mid(start, end - start));
+ start = match.capturedEnd();
+ }
+
+ if (start != size() || behavior == KeepEmptyParts)
+ list.append(mid(start));
+
+ return list;
+}
+#endif // QT_BOOTSTRAPPED
+#endif // QT_NO_REGEXP
+
/*!
\enum QString::NormalizationForm
@@ -7067,11 +7424,11 @@ QString QString::fromRawData(const QChar *unicode, int size)
} else {
x = static_cast<Data *>(::malloc(sizeof(Data) + sizeof(ushort)));
Q_CHECK_PTR(x);
- x->ref = 1;
+ x->ref.initializeOwned();
x->size = size;
x->alloc = 0;
x->capacityReserved = false;
- x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
+ x->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(x);
}
return QString(x, 0);
}
@@ -7092,14 +7449,14 @@ QString QString::fromRawData(const QChar *unicode, int size)
*/
QString &QString::setRawData(const QChar *unicode, int size)
{
- if (d->ref != 1 || d->alloc) {
+ if (d->ref.isShared() || d->alloc) {
*this = fromRawData(unicode, size);
} else {
if (unicode) {
d->size = size;
- d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort));
+ d->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(d);
} else {
- d->offset = 0;
+ d->offset = sizeof(QStringData);
d->size = 0;
}
}
@@ -7179,6 +7536,17 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa latin1()
*/
+/*! \fn QLatin1String::QLatin1String(const QByteArray &str)
+
+ Constructs a QLatin1String object that stores \a str.
+
+ The string data is \e not copied. The caller must be able to
+ guarantee that \a str will not be deleted or modified as long as
+ the QLatin1String object exists.
+
+ \sa latin1()
+*/
+
/*! \fn const char *QLatin1String::latin1() const
Returns the Latin-1 string stored in this object.
@@ -8059,15 +8427,17 @@ QStringRef QString::rightRef(int n) const
QStringRef QString::midRef(int position, int n) const
{
- if (d == &shared_null.str || position > d->size)
+ if (position > d->size)
return QStringRef();
- if (n < 0)
- n = d->size - position;
if (position < 0) {
+ if (n < 0 || n + position >= d->size)
+ return QStringRef(this, 0, d->size);
+ if (n + position <= 0)
+ return QStringRef();
+
n += position;
position = 0;
- }
- if (n + position > d->size)
+ } else if (n < 0 || n > d->size - position)
n = d->size - position;
return QStringRef(this, position, n);
}
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 4d02fbe66d..de5cd2cfa9 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
class QCharRef;
class QRegExp;
+class QRegularExpression;
class QStringList;
class QTextCodec;
class QLatin1String;
@@ -75,25 +76,24 @@ struct QStringData {
int size;
uint alloc : 31;
uint capacityReserved : 1;
- union {
- qptrdiff offset; // will always work as we add/subtract from a ushort ptr
- ushort d[sizeof(qptrdiff)/sizeof(ushort)];
- };
- inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
- inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
+
+ qptrdiff offset;
+
+ inline ushort *data() { return reinterpret_cast<ushort *>(reinterpret_cast<char *>(this) + offset); }
+ inline const ushort *data() const { return reinterpret_cast<const ushort *>(reinterpret_cast<const char *>(this) + offset); }
};
-template<int N> struct QConstStringData;
-template<int N> struct QConstStringDataPtr
+template<int N> struct QStaticStringData;
+template<int N> struct QStaticStringDataPtr
{
- const QConstStringData<N> *ptr;
+ const QStaticStringData<N> *ptr;
};
#if defined(Q_COMPILER_UNICODE_STRINGS)
-template<int N> struct QConstStringData
+template<int N> struct QStaticStringData
{
- const QStringData str;
- const char16_t data[N + 1];
+ QStringData str;
+ char16_t data[N + 1];
};
#define QT_UNICODE_LITERAL_II(str) u"" str
@@ -102,10 +102,10 @@ template<int N> struct QConstStringData
|| (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) \
|| (!defined(__SIZEOF_WCHAR_T__) && defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536))
// wchar_t is 2 bytes
-template<int N> struct QConstStringData
+template<int N> struct QStaticStringData
{
- const QStringData str;
- const wchar_t data[N + 1];
+ QStringData str;
+ wchar_t data[N + 1];
};
#if defined(Q_CC_MSVC)
@@ -115,21 +115,21 @@ template<int N> struct QConstStringData
#endif
#else
-template<int N> struct QConstStringData
+template<int N> struct QStaticStringData
{
- const QStringData str;
- const ushort data[N + 1];
+ QStringData str;
+ ushort data[N + 1];
};
#endif
#if defined(QT_UNICODE_LITERAL_II)
# define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
# if defined(Q_COMPILER_LAMBDA)
-# define QStringLiteral(str) ([]() -> QConstStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
+# define QStringLiteral(str) ([]() -> QStaticStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
- static const QConstStringData<Size> qstring_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
- QConstStringDataPtr<Size> holder = { &qstring_literal }; \
+ static const QStaticStringData<Size> qstring_literal = \
+ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QStringData) }, QT_UNICODE_LITERAL(str) }; \
+ QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
return holder; }())
# elif defined(Q_CC_GNU)
@@ -140,9 +140,9 @@ template<int N> struct QConstStringData
# define QStringLiteral(str) \
__extension__ ({ \
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
- static const QConstStringData<Size> qstring_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
- QConstStringDataPtr<Size> holder = { &qstring_literal }; \
+ static const QStaticStringData<Size> qstring_literal = \
+ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QStringData) }, QT_UNICODE_LITERAL(str) }; \
+ QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
holder; })
# endif
#endif
@@ -160,8 +160,7 @@ public:
typedef QStringData Data;
inline QString();
- QString(const QChar *unicode, int size); // Qt5: don't cap size < 0
- explicit QString(const QChar *unicode); // Qt5: merge with the above
+ explicit QString(const QChar *unicode, int size = -1);
QString(QChar c);
QString(int size, QChar c);
inline QString(const QLatin1String &latin1);
@@ -285,6 +284,13 @@ public:
inline bool contains(QRegExp &rx) const { return indexOf(rx) != -1; }
#endif
+#ifndef QT_NO_REGEXP
+ int indexOf(const QRegularExpression &re, int from = 0) const;
+ int lastIndexOf(const QRegularExpression &re, int from = -1) const;
+ bool contains(const QRegularExpression &re) const;
+ int count(const QRegularExpression &re) const;
+#endif
+
enum SectionFlag {
SectionDefault = 0x00,
SectionSkipEmpty = 0x01,
@@ -299,7 +305,9 @@ public:
#ifndef QT_NO_REGEXP
QString section(const QRegExp &reg, int start, int end = -1, SectionFlags flags = SectionDefault) const;
#endif
-
+#ifndef QT_NO_REGEXP
+ QString section(const QRegularExpression &re, int start, int end = -1, SectionFlags flags = SectionDefault) const;
+#endif
QString left(int n) const Q_REQUIRED_RESULT;
QString right(int n) const Q_REQUIRED_RESULT;
QString mid(int position, int n = -1) const Q_REQUIRED_RESULT;
@@ -340,7 +348,7 @@ public:
inline QString &prepend(const QLatin1String &s) { return insert(0, s); }
inline QString &operator+=(QChar c) {
- if (d->ref != 1 || d->size + 1 > int(d->alloc))
+ if (d->ref.isShared() || d->size + 1 > int(d->alloc))
realloc(grow(d->size + 1));
d->data()[d->size++] = c.unicode();
d->data()[d->size] = '\0';
@@ -372,6 +380,11 @@ public:
inline QString &remove(const QRegExp &rx)
{ return replace(rx, QString()); }
#endif
+#ifndef QT_NO_REGEXP
+ QString &replace(const QRegularExpression &re, const QString &after);
+ inline QString &remove(const QRegularExpression &re)
+ { return replace(re, QString()); }
+#endif
enum SplitBehavior { KeepEmptyParts, SkipEmptyParts };
@@ -382,7 +395,9 @@ public:
#ifndef QT_NO_REGEXP
QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
#endif
-
+#ifndef QT_NO_REGEXP
+ QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
+#endif
enum NormalizationForm {
NormalizationForm_D,
NormalizationForm_C,
@@ -592,9 +607,9 @@ public:
QString(int size, Qt::Initialization);
template <int n>
- inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
+ inline QString(const QStaticStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
template <int N>
- Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
+ Q_DECL_CONSTEXPR inline QString(QStaticStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
private:
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
@@ -606,8 +621,8 @@ private:
QString &operator=(const QByteArray &a);
#endif
- static const QConstStringData<1> shared_null;
- static const QConstStringData<1> shared_empty;
+ static const QStaticStringData<1> shared_null;
+ static const QStaticStringData<1> shared_empty;
Data *d;
inline QString(Data *dd, int /*dummy*/) : d(dd) {}
@@ -649,6 +664,7 @@ class QLatin1String
public:
Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) : m_size(sz), m_data(s) {}
+ Q_DECL_CONSTEXPR inline explicit QLatin1String(const QByteArray &s) : m_size(strlen(s.constData())), m_data(s.constData()) {}
inline const char *latin1() const { return m_data; }
inline int size() const { return m_size; }
@@ -709,9 +725,9 @@ inline QChar *QString::data()
inline const QChar *QString::constData() const
{ return reinterpret_cast<const QChar*>(d->data()); }
inline void QString::detach()
-{ if (d->ref != 1 || d->offset) realloc(); }
+{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) realloc(); }
inline bool QString::isDetached() const
-{ return d->ref == 1; }
+{ return !d->ref.isShared(); }
inline QString &QString::operator=(const QLatin1String &s)
{
*this = fromLatin1(s.latin1(), s.size());
@@ -874,7 +890,7 @@ inline QString::~QString() { if (!d->ref.deref()) free(d); }
inline void QString::reserve(int asize)
{
- if (d->ref != 1 || asize > int(d->alloc))
+ if (d->ref.isShared() || asize > int(d->alloc))
realloc(asize);
if (!d->capacityReserved) {
@@ -885,11 +901,12 @@ inline void QString::reserve(int asize)
inline void QString::squeeze()
{
- if (d->ref > 1 || d->size < int(d->alloc))
+ if (d->ref.isShared() || d->size < int(d->alloc))
realloc();
if (d->capacityReserved) {
- // cannot set unconditionally, since d could be the shared_null/shared_empty (which is const)
+ // cannot set unconditionally, since d could be shared_null or
+ // otherwise static.
d->capacityReserved = false;
}
}
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index e34425be7e..0eb8aa8903 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -219,9 +219,9 @@ template <> struct QConcatenable<QString> : private QAbstractConcatenable
}
};
-template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
+template <int N> struct QConcatenable<QStaticStringDataPtr<N> > : private QAbstractConcatenable
{
- typedef QConstStringDataPtr<N> type;
+ typedef QStaticStringDataPtr<N> type;
typedef QString ConvertTo;
enum { ExactSize = true };
static int size(const type &) { return N; }
@@ -324,9 +324,9 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
}
};
-template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
+template <int N> struct QConcatenable<QStaticByteArrayDataPtr<N> > : private QAbstractConcatenable
{
- typedef QConstByteArrayDataPtr<N> type;
+ typedef QStaticByteArrayDataPtr<N> type;
typedef QByteArray ConvertTo;
enum { ExactSize = false };
static int size(const type &) { return N; }
@@ -338,9 +338,8 @@ template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbs
#endif
static inline void appendTo(const type &ba, char *&out)
{
- const char *a = ba.ptr->data;
- while (*a)
- *out++ = *a++;
+ ::memcpy(out, ba.ptr->data, N);
+ out += N;
}
};
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 75c219bbc9..1a746dc061 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -54,15 +54,7 @@ static inline int alignmentThreshold()
return 2 * sizeof(void*);
}
-const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZER(-1), 0, 0, true, false, 0 };
-
-QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
-{
- QVectorData* p = (QVectorData *)::malloc(sizeofTypedData + (size - 1) * sizeofT);
- Q_CHECK_PTR(p);
- ::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT);
- return p;
-}
+const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
QVectorData *QVectorData::allocate(int size, int alignment)
{
@@ -84,11 +76,9 @@ void QVectorData::free(QVectorData *x, int alignment)
::free(x);
}
-int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive)
+int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT)
{
- if (excessive)
- return size + size / 2;
- return qAllocMore(size * sizeofT, sizeofTypedData - sizeofT) / sizeofT;
+ return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT;
}
/*!
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 4230e55ff5..c119ef43ae 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -65,37 +65,28 @@ QT_BEGIN_NAMESPACE
struct Q_CORE_EXPORT QVectorData
{
QtPrivate::RefCount ref;
- int alloc;
int size;
-#if defined(Q_PROCESSOR_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
- // workaround for bug in gcc 3.4.2
- uint sharable;
- uint capacity;
- uint reserved;
-#else
- uint sharable : 1;
- uint capacity : 1;
- uint reserved : 30;
-#endif
+ uint alloc : 31;
+ uint capacityReserved : 1;
+
+ qptrdiff offset;
+
+ void* data() { return reinterpret_cast<char *>(this) + this->offset; }
static const QVectorData shared_null;
- // ### Qt 5: rename to 'allocate()'. The current name causes problems for
- // some debugges when the QVector is member of a class within an unnamed namespace.
- // ### Qt 5: can be removed completely. (Ralf)
- static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init);
static QVectorData *allocate(int size, int alignment);
static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
static void free(QVectorData *data, int alignment);
- static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive);
+ static int grow(int sizeOfHeader, int size, int sizeOfT);
};
template <typename T>
-struct QVectorTypedData : private QVectorData
-{ // private inheritance as we must not access QVectorData member thought QVectorTypedData
- // as this would break strict aliasing rules. (in the case of shared_null)
- T array[1];
+struct QVectorTypedData : QVectorData
+{
+ T* begin() { return reinterpret_cast<T *>(this->data()); }
+ T* end() { return begin() + this->size; }
- static inline void free(QVectorTypedData<T> *x, int alignment) { QVectorData::free(static_cast<QVectorData *>(x), alignment); }
+ static QVectorTypedData *sharedNull() { return static_cast<QVectorTypedData *>(const_cast<QVectorData *>(&QVectorData::shared_null)); }
};
class QRegion;
@@ -104,27 +95,30 @@ template <typename T>
class QVector
{
typedef QVectorTypedData<T> Data;
- union {
- QVectorData *d;
-#if defined(Q_CC_SUN) && (__SUNPRO_CC <= 0x550)
- QVectorTypedData<T> *p;
-#else
- Data *p;
-#endif
- };
+ Data *d;
public:
- // ### Qt 5: Consider making QVector non-shared to get at least one
- // "really fast" container. See tests/benchmarks/corelib/tools/qvector/
- inline QVector() : d(const_cast<QVectorData *>(&QVectorData::shared_null)) { }
+ inline QVector() : d(Data::sharedNull()) { }
explicit QVector(int size);
QVector(int size, const T &t);
- inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
- inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
+ inline QVector(const QVector<T> &v)
+ {
+ if (v.d->ref.ref()) {
+ d = v.d;
+ } else {
+ d = Data::sharedNull();
+ realloc(0, int(v.d->alloc));
+ qCopy(v.d->begin(), v.d->end(), d->begin());
+ d->size = v.d->size;
+ d->capacityReserved = v.d->capacityReserved;
+ }
+ }
+
+ inline ~QVector() { if (!d->ref.deref()) free(d); }
QVector<T> &operator=(const QVector<T> &v);
#ifdef Q_COMPILER_RVALUE_REFS
inline QVector<T> operator=(QVector<T> &&other)
- { qSwap(p, other.p); return *this; }
+ { qSwap(d, other.d); return *this; }
#endif
inline void swap(QVector<T> &other) { qSwap(d, other.d); }
#ifdef Q_COMPILER_INITIALIZER_LISTS
@@ -139,18 +133,27 @@ public:
void resize(int size);
- inline int capacity() const { return d->alloc; }
+ inline int capacity() const { return int(d->alloc); }
void reserve(int size);
- inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; }
+ inline void squeeze() { realloc(d->size, d->size); d->capacityReserved = 0; }
+
+ inline void detach() { if (!isDetached()) detach_helper(); }
+ inline bool isDetached() const { return !d->ref.isShared(); }
+ inline void setSharable(bool sharable)
+ {
+ if (sharable == d->ref.isSharable())
+ return;
+ if (!sharable)
+ detach();
+ if (d != Data::sharedNull())
+ d->ref.setSharable(sharable);
+ }
- inline void detach() { if (d->ref != 1) detach_helper(); }
- inline bool isDetached() const { return d->ref == 1; }
- inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QVectorData::shared_null) d->sharable = sharable; }
inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
- inline T *data() { detach(); return p->array; }
- inline const T *data() const { return p->array; }
- inline const T *constData() const { return p->array; }
+ 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;
@@ -243,12 +246,12 @@ public:
typedef T* iterator;
typedef const T* const_iterator;
#endif
- inline iterator begin() { detach(); return p->array; }
- inline const_iterator begin() const { return p->array; }
- inline const_iterator constBegin() const { return p->array; }
- inline iterator end() { detach(); return p->array + d->size; }
- inline const_iterator end() const { return p->array + d->size; }
- inline const_iterator constEnd() const { return p->array + d->size; }
+ inline iterator begin() { detach(); return d->begin(); }
+ inline const_iterator begin() const { return d->begin(); }
+ inline const_iterator constBegin() const { return d->begin(); }
+ inline iterator end() { detach(); return d->end(); }
+ inline const_iterator end() const { return d->end(); }
+ inline const_iterator constEnd() const { return d->end(); }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(iterator begin, iterator end);
@@ -313,46 +316,49 @@ private:
friend class QRegion; // Optimization for QRegion::rects()
void detach_helper();
- QVectorData *malloc(int alloc);
+ Data *malloc(int alloc);
void realloc(int size, int alloc);
void free(Data *d);
- int sizeOfTypedData() {
- // this is more or less the same as sizeof(Data), except that it doesn't
- // count the padding at the end
- return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+
+ class AlignmentDummy { QVectorData header; T array[1]; };
+
+ static Q_DECL_CONSTEXPR int offsetOfTypedData()
+ {
+ // (non-POD)-safe offsetof(AlignmentDummy, array)
+ return (sizeof(QVectorData) + (alignOfTypedData() - 1)) & ~(alignOfTypedData() - 1);
}
- inline int alignOfTypedData() const
+ static Q_DECL_CONSTEXPR int alignOfTypedData()
{
#ifdef Q_ALIGNOF
- return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
+ return Q_ALIGNOF(AlignmentDummy);
#else
- return 0;
+ return sizeof(void *);
#endif
}
};
template <typename T>
void QVector<T>::detach_helper()
-{ realloc(d->size, d->alloc); }
+{ realloc(d->size, int(d->alloc)); }
template <typename T>
void QVector<T>::reserve(int asize)
-{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; }
+{ if (asize > int(d->alloc)) realloc(d->size, asize); if (isDetached()) d->capacityReserved = 1; }
template <typename T>
void QVector<T>::resize(int asize)
-{ realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
- QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
- : d->alloc); }
+{ realloc(asize, (asize > int(d->alloc) || (!d->capacityReserved && asize < d->size && asize < int(d->alloc >> 1))) ?
+ QVectorData::grow(offsetOfTypedData(), asize, sizeof(T))
+ : int(d->alloc)); }
template <typename T>
inline void QVector<T>::clear()
{ *this = QVector<T>(); }
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 p->array[i]; }
+ 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 p->array[i]; }
+ 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");
@@ -388,39 +394,37 @@ inline void QVector<T>::replace(int i, const T &t)
template <typename T>
QVector<T> &QVector<T>::operator=(const QVector<T> &v)
{
- QVectorData *o = v.d;
- o->ref.ref();
- if (!d->ref.deref())
- free(p);
- d = o;
- if (!d->sharable)
- detach_helper();
+ if (v.d != d) {
+ QVector<T> tmp(v);
+ tmp.swap(*this);
+ }
return *this;
}
template <typename T>
-inline QVectorData *QVector<T>::malloc(int aalloc)
+inline typename QVector<T>::Data *QVector<T>::malloc(int aalloc)
{
- QVectorData *vectordata = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
+ QVectorData *vectordata = QVectorData::allocate(offsetOfTypedData() + aalloc * sizeof(T), alignOfTypedData());
Q_CHECK_PTR(vectordata);
- return vectordata;
+ return static_cast<Data *>(vectordata);
}
template <typename T>
QVector<T>::QVector(int asize)
{
d = malloc(asize);
- d->ref = 1;
- d->alloc = d->size = asize;
- d->sharable = true;
- d->capacity = false;
+ d->ref.initializeOwned();
+ d->size = asize;
+ d->alloc = uint(d->size);
+ d->capacityReserved = false;
+ d->offset = offsetOfTypedData();
if (QTypeInfo<T>::isComplex) {
- T* b = p->array;
- T* i = p->array + d->size;
+ T* b = d->begin();
+ T* i = d->end();
while (i != b)
new (--i) T;
} else {
- qMemSet(p->array, 0, asize * sizeof(T));
+ qMemSet(d->begin(), 0, asize * sizeof(T));
}
}
@@ -428,12 +432,13 @@ template <typename T>
QVector<T>::QVector(int asize, const T &t)
{
d = malloc(asize);
- d->ref = 1;
- d->alloc = d->size = asize;
- d->sharable = true;
- d->capacity = false;
- T* i = p->array + d->size;
- while (i != p->array)
+ d->ref.initializeOwned();
+ d->size = asize;
+ d->alloc = uint(d->size);
+ d->capacityReserved = false;
+ d->offset = offsetOfTypedData();
+ T* i = d->end();
+ while (i != d->begin())
new (--i) T(t);
}
@@ -442,14 +447,22 @@ template <typename T>
QVector<T>::QVector(std::initializer_list<T> args)
{
d = malloc(int(args.size()));
- d->ref = 1;
- d->alloc = d->size = int(args.size());
- d->sharable = true;
- d->capacity = false;
- T* i = p->array + d->size;
- auto it = args.end();
- while (i != p->array)
- new (--i) T(*(--it));
+ d->ref.initializeOwned();
+ d->size = int(args.size());
+ d->alloc = uint(d->size);
+ d->capacityReserved = false;
+ d->offset = offsetOfTypedData();
+ if (QTypeInfo<T>::isComplex) {
+ T* b = d->begin();
+ T* i = d->end();
+ const T* s = args.end();
+ while (i != b)
+ new(--i) T(*--s);
+ } else {
+ // std::initializer_list<T>::iterator is guaranteed to be
+ // const T* ([support.initlist]/1), so can be memcpy'ed away from:
+ ::memcpy(d->begin(), args.begin(), args.size() * sizeof(T));
+ }
}
#endif
@@ -457,14 +470,12 @@ template <typename T>
void QVector<T>::free(Data *x)
{
if (QTypeInfo<T>::isComplex) {
- T* b = x->array;
- union { QVectorData *d; Data *p; } u;
- u.p = x;
- T* i = b + u.d->size;
+ T* b = x->begin();
+ T* i = b + x->size;
while (i-- != b)
i->~T();
}
- x->free(x, alignOfTypedData());
+ Data::free(x, alignOfTypedData());
}
template <typename T>
@@ -473,84 +484,82 @@ void QVector<T>::realloc(int asize, int aalloc)
Q_ASSERT(asize <= aalloc);
T *pOld;
T *pNew;
- union { QVectorData *d; Data *p; } x;
- x.d = d;
+ Data *x = d;
- if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
+ if (QTypeInfo<T>::isComplex && asize < d->size && isDetached()) {
// call the destructor on all objects that need to be
// destroyed when shrinking
- pOld = p->array + d->size;
- pNew = p->array + asize;
+ pOld = d->begin() + d->size;
+ pNew = d->begin() + asize;
while (asize < d->size) {
(--pOld)->~T();
d->size--;
}
}
- if (aalloc != d->alloc || d->ref != 1) {
+ if (aalloc != int(d->alloc) || !isDetached()) {
// (re)allocate memory
if (QTypeInfo<T>::isStatic) {
- x.d = malloc(aalloc);
- Q_CHECK_PTR(x.p);
- x.d->size = 0;
- } else if (d->ref != 1) {
- x.d = malloc(aalloc);
- Q_CHECK_PTR(x.p);
+ x = malloc(aalloc);
+ Q_CHECK_PTR(x);
+ x->size = 0;
+ } else if (!isDetached()) {
+ x = malloc(aalloc);
+ Q_CHECK_PTR(x);
if (QTypeInfo<T>::isComplex) {
- x.d->size = 0;
+ x->size = 0;
} else {
- ::memcpy(x.p, p, sizeOfTypedData() + (qMin(aalloc, d->alloc) - 1) * sizeof(T));
- x.d->size = d->size;
+ ::memcpy(x, d, offsetOfTypedData() + qMin(uint(aalloc), d->alloc) * sizeof(T));
+ x->size = d->size;
}
} else {
QT_TRY {
- QVectorData *mem = QVectorData::reallocate(d, sizeOfTypedData() + (aalloc - 1) * sizeof(T),
- sizeOfTypedData() + (d->alloc - 1) * sizeof(T), alignOfTypedData());
+ QVectorData *mem = QVectorData::reallocate(d, offsetOfTypedData() + aalloc * sizeof(T),
+ offsetOfTypedData() + d->alloc * sizeof(T), alignOfTypedData());
Q_CHECK_PTR(mem);
- x.d = d = mem;
- x.d->size = d->size;
+ x = d = static_cast<Data *>(mem);
+ x->size = d->size;
} QT_CATCH (const std::bad_alloc &) {
- if (aalloc > d->alloc) // ignore the error in case we are just shrinking.
+ if (aalloc > int(d->alloc)) // ignore the error in case we are just shrinking.
QT_RETHROW;
}
}
- x.d->ref = 1;
- x.d->alloc = aalloc;
- x.d->sharable = true;
- x.d->capacity = d->capacity;
- x.d->reserved = 0;
+ x->ref.initializeOwned();
+ x->alloc = uint(aalloc);
+ x->capacityReserved = d->capacityReserved;
+ x->offset = offsetOfTypedData();
}
if (QTypeInfo<T>::isComplex) {
QT_TRY {
- pOld = p->array + x.d->size;
- pNew = x.p->array + x.d->size;
+ pOld = d->begin() + x->size;
+ pNew = x->begin() + x->size;
// copy objects from the old array into the new array
const int toMove = qMin(asize, d->size);
- while (x.d->size < toMove) {
+ while (x->size < toMove) {
new (pNew++) T(*pOld++);
- x.d->size++;
+ x->size++;
}
// construct all new objects when growing
- while (x.d->size < asize) {
+ while (x->size < asize) {
new (pNew++) T;
- x.d->size++;
+ x->size++;
}
} QT_CATCH (...) {
- free(x.p);
+ free(x);
QT_RETHROW;
}
- } else if (asize > x.d->size) {
+ } else if (asize > x->size) {
// initialize newly allocated memory to 0
- qMemSet(x.p->array + x.d->size, 0, (asize - x.d->size) * sizeof(T));
+ qMemSet(x->end(), 0, (asize - x->size) * sizeof(T));
}
- x.d->size = asize;
+ x->size = asize;
- if (d != x.d) {
+ if (d != x) {
if (!d->ref.deref())
- free(p);
- d = x.d;
+ free(d);
+ d = x;
}
}
@@ -560,31 +569,31 @@ Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
if (i < 0 || i >= d->size) {
return T();
}
- return p->array[i];
+ return d->begin()[i];
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
{
- return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
+ return ((i < 0 || i >= d->size) ? defaultValue : d->begin()[i]);
}
template <typename T>
void QVector<T>::append(const T &t)
{
- if (d->ref != 1 || d->size + 1 > d->alloc) {
+ if (!isDetached() || d->size + 1 > int(d->alloc)) {
const T copy(t);
- realloc(d->size, (d->size + 1 > d->alloc) ?
- QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), QTypeInfo<T>::isStatic)
- : d->alloc);
+ realloc(d->size, (d->size + 1 > int(d->alloc)) ?
+ QVectorData::grow(offsetOfTypedData(), d->size + 1, sizeof(T))
+ : int(d->alloc));
if (QTypeInfo<T>::isComplex)
- new (p->array + d->size) T(copy);
+ new (d->end()) T(copy);
else
- p->array[d->size] = copy;
+ *d->end() = copy;
} else {
if (QTypeInfo<T>::isComplex)
- new (p->array + d->size) T(t);
+ new (d->end()) T(t);
else
- p->array[d->size] = t;
+ *d->end() = t;
}
++d->size;
}
@@ -592,27 +601,26 @@ void QVector<T>::append(const T &t)
template <typename T>
typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
{
- int offset = int(before - p->array);
+ int offset = int(before - d->begin());
if (n != 0) {
const T copy(t);
- if (d->ref != 1 || d->size + n > d->alloc)
- realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
- QTypeInfo<T>::isStatic));
+ if (!isDetached() || d->size + n > int(d->alloc))
+ realloc(d->size, QVectorData::grow(offsetOfTypedData(), d->size + n, sizeof(T)));
if (QTypeInfo<T>::isStatic) {
- T *b = p->array + d->size;
- T *i = p->array + d->size + n;
+ T *b = d->end();
+ T *i = d->end() + n;
while (i != b)
new (--i) T;
- i = p->array + d->size;
+ i = d->end();
T *j = i + n;
- b = p->array + offset;
+ b = d->begin() + offset;
while (i != b)
*--j = *--i;
i = b+n;
while (i != b)
*--i = copy;
} else {
- T *b = p->array + offset;
+ T *b = d->begin() + offset;
T *i = b + n;
memmove(i, b, (d->size - offset) * sizeof(T));
while (i != b)
@@ -620,29 +628,29 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
}
d->size += n;
}
- return p->array + offset;
+ return d->begin() + offset;
}
template <typename T>
typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
- int f = int(abegin - p->array);
- int l = int(aend - p->array);
+ int f = int(abegin - d->begin());
+ int l = int(aend - d->begin());
int n = l - f;
detach();
if (QTypeInfo<T>::isComplex) {
- qCopy(p->array+l, p->array+d->size, p->array+f);
- T *i = p->array+d->size;
- T* b = p->array+d->size-n;
+ qCopy(d->begin()+l, d->end(), d->begin()+f);
+ T *i = d->end();
+ T* b = d->end()-n;
while (i != b) {
--i;
i->~T();
}
} else {
- memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
+ memmove(d->begin() + f, d->begin() + l, (d->size-l)*sizeof(T));
}
d->size -= n;
- return p->array + f;
+ return d->begin() + f;
}
template <typename T>
@@ -652,9 +660,9 @@ bool QVector<T>::operator==(const QVector<T> &v) const
return false;
if (d == v.d)
return true;
- T* b = p->array;
+ T* b = d->begin();
T* i = b + d->size;
- T* j = v.p->array + d->size;
+ T* j = v.d->end();
while (i != b)
if (!(*--i == *--j))
return false;
@@ -667,8 +675,8 @@ 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 = p->array + d->size;
- T *b = p->array;
+ T *i = d->end();
+ T *b = d->begin();
while (i != b)
*--i = copy;
}
@@ -681,9 +689,9 @@ QVector<T> &QVector<T>::operator+=(const QVector &l)
int newSize = d->size + l.d->size;
realloc(d->size, newSize);
- T *w = p->array + newSize;
- T *i = l.p->array + l.d->size;
- T *b = l.p->array;
+ 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);
@@ -700,11 +708,11 @@ int QVector<T>::indexOf(const T &t, int from) const
if (from < 0)
from = qMax(from + d->size, 0);
if (from < d->size) {
- T* n = p->array + from - 1;
- T* e = p->array + d->size;
+ T* n = d->begin() + from - 1;
+ T* e = d->end();
while (++n != e)
if (*n == t)
- return n - p->array;
+ return n - d->begin();
}
return -1;
}
@@ -717,8 +725,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
else if (from >= d->size)
from = d->size-1;
if (from >= 0) {
- T* b = p->array;
- T* n = p->array + from + 1;
+ T* b = d->begin();
+ T* n = d->begin() + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
@@ -730,8 +738,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
template <typename T>
bool QVector<T>::contains(const T &t) const
{
- T* b = p->array;
- T* i = p->array + d->size;
+ T* b = d->begin();
+ T* i = d->end();
while (i != b)
if (*--i == t)
return true;
@@ -742,8 +750,8 @@ template <typename T>
int QVector<T>::count(const T &t) const
{
int c = 0;
- T* b = p->array;
- T* i = p->array + d->size;
+ T* b = d->begin();
+ T* i = d->end();
while (i != b)
if (*--i == t)
++c;
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 250789a969..ac347404fd 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -2,6 +2,9 @@
HEADERS += \
tools/qalgorithms.h \
+ tools/qarraydata.h \
+ tools/qarraydataops.h \
+ tools/qarraydatapointer.h \
tools/qbitarray.h \
tools/qbytearray.h \
tools/qbytearraymatcher.h \
@@ -56,6 +59,7 @@ HEADERS += \
SOURCES += \
+ tools/qarraydata.cpp \
tools/qbitarray.cpp \
tools/qbytearray.cpp \
tools/qbytearraymatcher.cpp \
diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp
index 7f4d8e7f33..9e3bd5c5d6 100644
--- a/src/dbus/qdbus_symbols.cpp
+++ b/src/dbus/qdbus_symbols.cpp
@@ -52,6 +52,7 @@ void (*qdbus_resolve_me(const char *name))();
#if !defined QT_LINKED_LIBDBUS
+#ifndef QT_BOOTSTRAPPED
static QLibrary *qdbus_libdbus = 0;
void qdbus_unloadLibDBus()
@@ -59,9 +60,11 @@ void qdbus_unloadLibDBus()
delete qdbus_libdbus;
qdbus_libdbus = 0;
}
+#endif
bool qdbus_loadLibDBus()
{
+#ifndef QT_BOOTSTRAPPED
#ifdef QT_BUILD_INTERNAL
// this is to simulate a library load failure for our autotest suite.
if (!qgetenv("QT_SIMULATE_DBUS_LIBFAIL").isEmpty())
@@ -93,17 +96,23 @@ bool qdbus_loadLibDBus()
delete lib;
lib = 0;
return false;
+#else
+ return true;
+#endif
}
+#ifndef QT_BOOTSTRAPPED
void (*qdbus_resolve_conditionally(const char *name))()
{
if (qdbus_loadLibDBus())
return qdbus_libdbus->resolve(name);
return 0;
}
+#endif
void (*qdbus_resolve_me(const char *name))()
{
+#ifndef QT_BOOTSTRAPPED
if (!qdbus_loadLibDBus())
qFatal("Cannot find libdbus-1 in your system to resolve symbol '%s'.", name);
@@ -112,9 +121,15 @@ void (*qdbus_resolve_me(const char *name))()
qFatal("Cannot resolve '%s' in your libdbus-1.", name);
return ptr;
+#else
+ Q_UNUSED(name);
+ return 0;
+#endif
}
+#ifndef QT_BOOTSTRAPPED
Q_DESTRUCTOR_FUNCTION(qdbus_unloadLibDBus)
+#endif
#endif // QT_LINKED_LIBDBUS
diff --git a/src/dbus/qdbusabstractadaptor.cpp b/src/dbus/qdbusabstractadaptor.cpp
index 7bdd947a37..bacf93bac8 100644
--- a/src/dbus/qdbusabstractadaptor.cpp
+++ b/src/dbus/qdbusabstractadaptor.cpp
@@ -181,7 +181,7 @@ void QDBusAbstractAdaptor::setAutoRelaySignals(bool enable)
continue;
// try to connect/disconnect to a signal on the parent that has the same method signature
- QByteArray sig = QMetaObject::normalizedSignature(mm.signature());
+ QByteArray sig = QMetaObject::normalizedSignature(mm.methodSignature().constData());
if (them->indexOfSignal(sig) == -1)
continue;
sig.prepend(QSIGNAL_CODE + '0');
@@ -307,7 +307,7 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **
// invalid signal signature
// qDBusParametersForMethod has not yet complained about this one
qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s",
- senderMetaObject->className(), mm.signature());
+ senderMetaObject->className(), mm.methodSignature().constData());
return;
}
@@ -323,10 +323,38 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **
// modify carefully: this has been hand-edited!
// the relaySlot slot gets called with the void** array
+struct qt_meta_stringdata_QDBusAdaptorConnector_t {
+ QByteArrayData data[10];
+ char stringdata[96];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) { \
+ Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \
+ offsetof(qt_meta_stringdata_QDBusAdaptorConnector_t, stringdata) + ofs \
+ - idx * sizeof(QByteArrayData) \
+ }
+static const qt_meta_stringdata_QDBusAdaptorConnector_t qt_meta_stringdata_QDBusAdaptorConnector = {
+ {
+QT_MOC_LITERAL(0, 0, 21),
+QT_MOC_LITERAL(1, 22, 11),
+QT_MOC_LITERAL(2, 34, 0),
+QT_MOC_LITERAL(3, 35, 3),
+QT_MOC_LITERAL(4, 39, 18),
+QT_MOC_LITERAL(5, 58, 10),
+QT_MOC_LITERAL(6, 69, 3),
+QT_MOC_LITERAL(7, 73, 4),
+QT_MOC_LITERAL(8, 78, 9),
+QT_MOC_LITERAL(9, 88, 6)
+ },
+ "QDBusAdaptorConnector\0relaySignal\0\0"
+ "obj\0const QMetaObject*\0metaObject\0sid\0"
+ "args\0relaySlot\0polish\0"
+};
+#undef QT_MOC_LITERAL
+
static const uint qt_meta_data_QDBusAdaptorConnector[] = {
// content:
- 6, // revision
+ 7, // revision
0, // classname
0, 0, // classinfo
3, 14, // methods
@@ -336,20 +364,21 @@ static const uint qt_meta_data_QDBusAdaptorConnector[] = {
0, // flags
1, // signalCount
- // signals: signature, parameters, type, tag, flags
- 47, 23, 22, 22, 0x05,
+ // signals: name, argc, parameters, tag, flags
+ 1, 4, 29, 2, 0x05,
- // slots: signature, parameters, type, tag, flags
- 105, 22, 22, 22, 0x0a,
- 117, 22, 22, 22, 0x0a,
+ // slots: name, argc, parameters, tag, flags
+ 8, 0, 38, 2, 0x0a,
+ 9, 0, 39, 2, 0x0a,
- 0 // eod
-};
+ // signals: parameters
+ QMetaType::Void, QMetaType::QObjectStar, 0x80000000 | 4, QMetaType::Int, QMetaType::QVariantList, 3, 5, 6, 7,
-static const char qt_meta_stringdata_QDBusAdaptorConnector[] = {
- "QDBusAdaptorConnector\0\0obj,metaObject,sid,args\0"
- "relaySignal(QObject*,const QMetaObject*,int,QVariantList)\0"
- "relaySlot()\0polish()\0"
+ // slots: parameters
+ QMetaType::Void,
+ QMetaType::Void,
+
+ 0 // eod
};
void QDBusAdaptorConnector::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
@@ -371,7 +400,7 @@ const QMetaObjectExtraData QDBusAdaptorConnector::staticMetaObjectExtraData = {
};
const QMetaObject QDBusAdaptorConnector::staticMetaObject = {
- { &QObject::staticMetaObject, qt_meta_stringdata_QDBusAdaptorConnector,
+ { &QObject::staticMetaObject, qt_meta_stringdata_QDBusAdaptorConnector.data,
qt_meta_data_QDBusAdaptorConnector, &staticMetaObjectExtraData }
};
@@ -383,7 +412,7 @@ const QMetaObject *QDBusAdaptorConnector::metaObject() const
void *QDBusAdaptorConnector::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector))
+ if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector.stringdata))
return static_cast<void*>(const_cast< QDBusAdaptorConnector*>(this));
return QObject::qt_metacast(_clname);
}
diff --git a/src/dbus/qdbusabstractadaptor.h b/src/dbus/qdbusabstractadaptor.h
index 75a3876b1b..bb12c74823 100644
--- a/src/dbus/qdbusabstractadaptor.h
+++ b/src/dbus/qdbusabstractadaptor.h
@@ -57,7 +57,7 @@ class Q_DBUS_EXPORT QDBusAbstractAdaptor: public QObject
{
Q_OBJECT
protected:
- QDBusAbstractAdaptor(QObject *parent);
+ explicit QDBusAbstractAdaptor(QObject *parent);
public:
~QDBusAbstractAdaptor();
diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp
index eeaf0b13eb..941f322315 100644
--- a/src/dbus/qdbusabstractinterface.cpp
+++ b/src/dbus/qdbusabstractinterface.cpp
@@ -148,7 +148,7 @@ void QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, QVariant &
QDBusMessage reply = connection.call(msg, QDBus::Block, timeout);
if (reply.type() != QDBusMessage::ReplyMessage) {
- lastError = reply;
+ lastError = QDBusError(reply);
where.clear();
return;
}
@@ -214,7 +214,7 @@ bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const Q
QDBusMessage reply = connection.call(msg, QDBus::Block, timeout);
if (reply.type() != QDBusMessage::ReplyMessage) {
- lastError = reply;
+ lastError = QDBusError(reply);
return false;
}
return true;
@@ -446,7 +446,7 @@ QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode,
for (int i = staticMetaObject.methodCount(); i < mo->methodCount(); ++i) {
QMetaMethod mm = mo->method(i);
- if (QByteArray(mm.signature()).startsWith(match)) {
+ if (mm.methodSignature().startsWith(match)) {
// found a method with the same name as what we're looking for
// hopefully, nobody is overloading asynchronous and synchronous methods with
// the same name
@@ -467,7 +467,7 @@ QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode,
QDBusMessage reply = d->connection.call(msg, mode, d->timeout);
if (thread() == QThread::currentThread())
- d->lastError = reply; // will clear if reply isn't an error
+ d->lastError = QDBusError(reply); // will clear if reply isn't an error
// ensure that there is at least one element
if (reply.arguments().isEmpty())
@@ -540,7 +540,7 @@ bool QDBusAbstractInterface::callWithCallback(const QString &method,
QDBusMessagePrivate::setParametersValidated(msg, true);
msg.setArguments(args);
- d->lastError = 0;
+ d->lastError = QDBusError();
return d->connection.callWithCallback(msg,
receiver,
returnMethod,
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index ad620fd7a6..8dd2622f7c 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -127,7 +127,7 @@ public:
};
Q_DECLARE_FLAGS(ConnectionCapabilities, ConnectionCapability)
- QDBusConnection(const QString &name);
+ explicit QDBusConnection(const QString &name);
QDBusConnection(const QDBusConnection &other);
~QDBusConnection();
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 41a1341e40..caeb116b31 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -88,6 +88,8 @@ class QDBusAbstractInterface;
class QDBusConnectionInterface;
class QDBusPendingCallPrivate;
+#ifndef QT_BOOTSTRAPPED
+
class QDBusErrorInternal
{
mutable DBusError error;
@@ -336,7 +338,10 @@ public:
// in qdbusmisc.cpp
extern int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes);
+#endif // QT_BOOTSTRAPPED
+extern int qDBusParametersForMethod(const QList<QByteArray> &parameters, QList<int>& metaTypes);
extern bool qDBusCheckAsyncTag(const char *tag);
+#ifndef QT_BOOTSTRAPPED
extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name);
extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo);
@@ -348,6 +353,7 @@ extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNod
const QDBusMessage &msg);
extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node,
const QDBusMessage &msg);
+#endif // QT_BOOTSTRAPPED
QT_END_NAMESPACE
diff --git a/src/dbus/qdbuserror.cpp b/src/dbus/qdbuserror.cpp
index 9db279e005..713ef75a93 100644
--- a/src/dbus/qdbuserror.cpp
+++ b/src/dbus/qdbuserror.cpp
@@ -44,9 +44,11 @@
#include <qdebug.h>
#include <qvarlengtharray.h>
+#ifndef QT_BOOTSTRAPPED
#include "qdbus_symbols_p.h"
#include "qdbusmessage.h"
#include "qdbusmessage_p.h"
+#endif
#ifndef QT_NO_DBUS
@@ -239,6 +241,7 @@ static inline QDBusError::ErrorType get(const char *name)
\value UnknownObject The remote object could not be found.
*/
+#ifndef QT_BOOTSTRAPPED
/*!
\internal
Constructs a QDBusError from a DBusError structure.
@@ -268,6 +271,7 @@ QDBusError::QDBusError(const QDBusMessage &qdmsg)
nm = qdmsg.errorName();
msg = qdmsg.errorMessage();
}
+#endif
/*!
\internal
@@ -302,6 +306,26 @@ QDBusError &QDBusError::operator=(const QDBusError &other)
return *this;
}
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \internal
+ Assignment operator from a QDBusMessage
+*/
+QDBusError &QDBusError::operator=(const QDBusMessage &qdmsg)
+{
+ if (qdmsg.type() == QDBusMessage::ErrorMessage) {
+ code = ::get(qdmsg.errorName().toUtf8().constData());
+ nm = qdmsg.errorName();
+ msg = qdmsg.errorMessage();
+ } else {
+ code =NoError;
+ nm.clear();
+ msg.clear();
+ }
+ return *this;
+}
+#endif
+
/*!
Returns this error's ErrorType.
diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h
index 0cea8e2cde..b73ad34db1 100644
--- a/src/dbus/qdbuserror.h
+++ b/src/dbus/qdbuserror.h
@@ -93,11 +93,16 @@ public:
#endif
};
- QDBusError(const DBusError *error = 0);
- QDBusError(const QDBusMessage& msg);
+#ifndef QT_BOOTSTRAPPED
+ explicit QDBusError(const DBusError *error = 0);
+ /*implicit*/ QDBusError(const QDBusMessage& msg);
+#endif
QDBusError(ErrorType error, const QString &message);
QDBusError(const QDBusError &other);
QDBusError &operator=(const QDBusError &other);
+#ifndef QT_BOOTSTRAPPED
+ QDBusError &operator=(const QDBusMessage &msg);
+#endif
ErrorType type() const;
QString name() const;
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index f0c8224be2..acb83e274a 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -640,7 +640,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
continue;
// check name:
- QByteArray slotname = mm.signature();
+ QByteArray slotname = mm.methodSignature();
int paren = slotname.indexOf('(');
if (paren != name.length() || !slotname.startsWith(name))
continue;
@@ -686,7 +686,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
++i;
// make sure that the output parameters have signatures too
- if (returnType != 0 && QDBusMetaType::typeToSignature(returnType) == 0)
+ if (returnType != QMetaType::UnknownType && returnType != QMetaType::Void && QDBusMetaType::typeToSignature(returnType) == 0)
continue;
bool ok = true;
@@ -919,7 +919,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
// output arguments
QVariantList outputArgs;
void *null = 0;
- if (metaTypes[0] != QMetaType::Void) {
+ if (metaTypes[0] != QMetaType::Void && metaTypes[0] != QMetaType::UnknownType) {
QVariant arg(metaTypes[0], null);
outputArgs.append( arg );
params[0] = const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData());
@@ -1188,7 +1188,7 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in
QString interface = qDBusInterfaceFromMetaObject(mo);
QMetaMethod mm = mo->method(signalId);
- QByteArray memberName = mm.signature();
+ QByteArray memberName = mm.methodSignature();
memberName.truncate(memberName.indexOf('('));
// check if it's scriptable
@@ -1928,7 +1928,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
}
QDBusMessage reply = pcall->replyMessage;
- lastError = reply; // set or clear error
+ lastError = QDBusError(reply); // set or clear error
delete pcall;
return reply;
@@ -2368,7 +2368,7 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa
// fetch the XML description
xml = reply.arguments().at(0).toString();
} else {
- error = reply;
+ error = QDBusError(reply);
lastError = error;
if (reply.type() != QDBusMessage::ErrorMessage || error.type() != QDBusError::UnknownMethod)
return 0; // error
diff --git a/src/dbus/qdbusinterface.cpp b/src/dbus/qdbusinterface.cpp
index d390f395ee..b336396f3b 100644
--- a/src/dbus/qdbusinterface.cpp
+++ b/src/dbus/qdbusinterface.cpp
@@ -280,7 +280,7 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv)
} else if (mm.methodType() == QMetaMethod::Slot || mm.methodType() == QMetaMethod::Method) {
// method call relay from Qt world to D-Bus world
// get D-Bus equivalent signature
- QString methodName = QLatin1String(metaObject->dbusNameForMethod(id));
+ QString methodName = QString::fromLatin1(mm.name());
const int *inputTypes = metaObject->inputTypesForMethod(id);
int inputTypesCount = *inputTypes;
@@ -316,7 +316,7 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv)
}
// done
- lastError = reply;
+ lastError = QDBusError(reply);
return -1;
}
}
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index bd7b83bf65..ce8146f639 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -54,6 +54,7 @@
#include "qdbusabstractinterface_p.h"
#include <private/qmetaobject_p.h>
+#include <private/qmetaobjectbuilder_p.h>
#ifndef QT_NO_DBUS
@@ -69,8 +70,7 @@ public:
private:
struct Method {
- QByteArray parameters;
- QByteArray typeName;
+ QList<QByteArray> parameterNames;
QByteArray tag;
QByteArray name;
QVarLengthArray<int, 4> inputTypes;
@@ -103,10 +103,12 @@ private:
void parseMethods();
void parseSignals();
void parseProperties();
+
+ static int aggregateParameterCount(const QMap<QByteArray, Method> &map);
};
static const int intsPerProperty = 2;
-static const int intsPerMethod = 3;
+static const int intsPerMethod = 2;
struct QDBusMetaObjectPrivate : public QMetaObjectPrivate
{
@@ -132,6 +134,30 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature,
const QDBusIntrospection::Annotations &annotations,
const char *direction, int id)
{
+ struct QDBusRawTypeHandler {
+ static void destroy(void *)
+ {
+ qFatal("Cannot destroy placeholder type QDBusRawType");
+ }
+
+ static void *create(const void *)
+ {
+ qFatal("Cannot create placeholder type QDBusRawType");
+ return 0;
+ }
+
+ static void destruct(void *)
+ {
+ qFatal("Cannot destruct placeholder type QDBusRawType");
+ }
+
+ static void *construct(void *, const void *)
+ {
+ qFatal("Cannot construct placeholder type QDBusRawType");
+ return 0;
+ }
+ };
+
Type result;
result.id = QVariant::Invalid;
@@ -157,8 +183,13 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature,
if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) {
// type is still unknown or doesn't match back to the signature that it
// was expected to, so synthesize a fake type
- type = QMetaType::VoidStar;
typeName = "QDBusRawType<0x" + signature.toHex() + ">*";
+ type = QMetaType::registerType(typeName, QDBusRawTypeHandler::destroy,
+ QDBusRawTypeHandler::create,
+ QDBusRawTypeHandler::destruct,
+ QDBusRawTypeHandler::construct,
+ sizeof(void *),
+ QMetaType::MovableType);
}
result.name = typeName;
@@ -215,8 +246,7 @@ void QDBusMetaObjectGenerator::parseMethods()
mm.inputTypes.append(type.id);
- mm.parameters.append(arg.name.toLatin1());
- mm.parameters.append(',');
+ mm.parameterNames.append(arg.name.toLatin1());
prototype.append(type.name);
prototype.append(',');
@@ -235,13 +265,9 @@ void QDBusMetaObjectGenerator::parseMethods()
mm.outputTypes.append(type.id);
- if (i == 0) {
- // return value
- mm.typeName = type.name;
- } else {
+ if (i != 0) {
// non-const ref parameter
- mm.parameters.append(arg.name.toLatin1());
- mm.parameters.append(',');
+ mm.parameterNames.append(arg.name.toLatin1());
prototype.append(type.name);
prototype.append("&,");
@@ -250,12 +276,10 @@ void QDBusMetaObjectGenerator::parseMethods()
if (!ok) continue;
// convert the last commas:
- if (!mm.parameters.isEmpty()) {
- mm.parameters.truncate(mm.parameters.length() - 1);
+ if (!mm.parameterNames.isEmpty())
prototype[prototype.length() - 1] = ')';
- } else {
+ else
prototype.append(')');
- }
// check the async tag
if (m.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"))
@@ -295,8 +319,7 @@ void QDBusMetaObjectGenerator::parseSignals()
mm.inputTypes.append(type.id);
- mm.parameters.append(arg.name.toLatin1());
- mm.parameters.append(',');
+ mm.parameterNames.append(arg.name.toLatin1());
prototype.append(type.name);
prototype.append(',');
@@ -304,12 +327,10 @@ void QDBusMetaObjectGenerator::parseSignals()
if (!ok) continue;
// convert the last commas:
- if (!mm.parameters.isEmpty()) {
- mm.parameters.truncate(mm.parameters.length() - 1);
+ if (!mm.parameterNames.isEmpty())
prototype[prototype.length() - 1] = ')';
- } else {
+ else
prototype.append(')');
- }
// meta method flags
mm.flags = AccessProtected | MethodSignal | MethodScriptable;
@@ -342,49 +363,27 @@ void QDBusMetaObjectGenerator::parseProperties()
if (p.access != QDBusIntrospection::Property::Read)
mp.flags |= Writable;
- if (mp.typeName == "QDBusVariant")
- mp.flags |= QMetaType::QVariant << 24;
- else if (mp.type < 0xff)
- // encode the type in the flags
- mp.flags |= mp.type << 24;
-
// add the property:
properties.insert(name, mp);
}
}
-void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
+// Returns the sum of all parameters (including return type) for the given
+// \a map of methods. This is needed for calculating the size of the methods'
+// parameter type/name meta-data.
+int QDBusMetaObjectGenerator::aggregateParameterCount(const QMap<QByteArray, Method> &map)
{
- class MetaStringTable
- {
- public:
- typedef QHash<QByteArray, int> Entries; // string --> offset mapping
- typedef Entries::const_iterator const_iterator;
- Entries::const_iterator constBegin() const
- { return m_entries.constBegin(); }
- Entries::const_iterator constEnd() const
- { return m_entries.constEnd(); }
-
- MetaStringTable() : m_offset(0) {}
-
- int enter(const QByteArray &value)
- {
- Entries::iterator it = m_entries.find(value);
- if (it != m_entries.end())
- return it.value();
- int pos = m_offset;
- m_entries.insert(value, pos);
- m_offset += value.size() + 1;
- return pos;
- }
-
- int arraySize() const { return m_offset; }
-
- private:
- Entries m_entries;
- int m_offset;
- };
+ int sum = 0;
+ QMap<QByteArray, Method>::const_iterator it;
+ for (it = map.constBegin(); it != map.constEnd(); ++it) {
+ const Method &m = it.value();
+ sum += m.inputTypes.size() + qMax(1, m.outputTypes.size());
+ }
+ return sum;
+}
+void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
+{
// this code here is mostly copied from qaxbase.cpp
// with a few modifications to make it cleaner
@@ -396,8 +395,14 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
QVarLengthArray<int> idata;
idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
+ int methodParametersDataSize =
+ ((aggregateParameterCount(signals_)
+ + aggregateParameterCount(methods)) * 2) // types and parameter names
+ - signals_.count() // return "parameters" don't have names
+ - methods.count(); // ditto
+
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
- Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 6, "QtDBus meta-object generator should generate the same version as moc");
+ Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QtDBus meta-object generator should generate the same version as moc");
header->revision = QMetaObjectPrivate::OutputRevision;
header->className = 0;
header->classInfoCount = 0;
@@ -405,7 +410,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
header->methodCount = signals_.count() + methods.count();
header->methodData = idata.size();
header->propertyCount = properties.count();
- header->propertyData = header->methodData + header->methodCount * 5;
+ header->propertyData = header->methodData + header->methodCount * 5 + methodParametersDataSize;
header->enumeratorCount = 0;
header->enumeratorData = 0;
header->constructorCount = 0;
@@ -417,7 +422,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;
int data_size = idata.size() +
- (header->methodCount * (5+intsPerMethod)) +
+ (header->methodCount * (5+intsPerMethod)) + methodParametersDataSize +
(header->propertyCount * (3+intsPerProperty));
foreach (const Method &mm, signals_)
data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
@@ -425,10 +430,11 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
idata.resize(data_size + 1);
- MetaStringTable strings;
+ QMetaStringTable strings;
strings.enter(className.toLatin1());
int offset = header->methodData;
+ int parametersOffset = offset + header->methodCount * 5;
int signatureOffset = header->methodDBusData;
int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod;
idata[typeidOffset++] = 0; // eod
@@ -439,16 +445,45 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
QMap<QByteArray, Method> &map = (x == 0) ? signals_ : methods;
for (QMap<QByteArray, Method>::ConstIterator it = map.constBegin();
it != map.constEnd(); ++it) {
- // form "prototype\0parameters\0typeName\0tag\0methodname\0"
const Method &mm = it.value();
- idata[offset++] = strings.enter(it.key()); // prototype
- idata[offset++] = strings.enter(mm.parameters);
- idata[offset++] = strings.enter(mm.typeName);
+ int argc = mm.inputTypes.size() + qMax(0, mm.outputTypes.size() - 1);
+
+ idata[offset++] = strings.enter(mm.name);
+ idata[offset++] = argc;
+ idata[offset++] = parametersOffset;
idata[offset++] = strings.enter(mm.tag);
idata[offset++] = mm.flags;
- idata[signatureOffset++] = strings.enter(mm.name);
+ // Parameter types
+ for (int i = -1; i < argc; ++i) {
+ int type;
+ QByteArray typeName;
+ if (i < 0) { // Return type
+ if (!mm.outputTypes.isEmpty())
+ type = mm.outputTypes.first();
+ else
+ type = QMetaType::Void;
+ } else if (i < mm.inputTypes.size()) {
+ type = mm.inputTypes.at(i);
+ } else {
+ Q_ASSERT(mm.outputTypes.size() > 1);
+ type = mm.outputTypes.at(i - mm.inputTypes.size() + 1);
+ // Output parameters are references; type id not available
+ typeName = QMetaType::typeName(type);
+ typeName.append('&');
+ }
+ Q_ASSERT(type != QMetaType::UnknownType);
+ int typeInfo;
+ if (!typeName.isEmpty())
+ typeInfo = IsUnresolvedType | strings.enter(typeName);
+ else
+ typeInfo = type;
+ idata[parametersOffset++] = typeInfo;
+ }
+ // Parameter names
+ for (int i = 0; i < argc; ++i)
+ idata[parametersOffset++] = strings.enter(mm.parameterNames.at(i));
idata[signatureOffset++] = typeidOffset;
idata[typeidOffset++] = mm.inputTypes.count();
@@ -462,9 +497,12 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
}
}
- Q_ASSERT(offset == header->propertyData);
+ Q_ASSERT(offset == header->methodData + header->methodCount * 5);
+ Q_ASSERT(parametersOffset = header->propertyData);
Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod);
Q_ASSERT(typeidOffset == idata.size());
+ offset += methodParametersDataSize;
+ Q_ASSERT(offset == header->propertyData);
// add each property
signatureOffset = header->propertyDBusData;
@@ -472,9 +510,10 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
it != properties.constEnd(); ++it) {
const Property &mp = it.value();
- // form is "name\0typeName\0signature\0"
+ // form is name, typeinfo, flags
idata[offset++] = strings.enter(it.key()); // name
- idata[offset++] = strings.enter(mp.typeName);
+ Q_ASSERT(mp.type != QMetaType::UnknownType);
+ idata[offset++] = mp.type;
idata[offset++] = mp.flags;
idata[signatureOffset++] = strings.enter(mp.signature);
@@ -484,14 +523,8 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
Q_ASSERT(offset == header->propertyDBusData);
Q_ASSERT(signatureOffset == header->methodDBusData);
- char *string_data = new char[strings.arraySize()];
- {
- MetaStringTable::const_iterator it;
- for (it = strings.constBegin(); it != strings.constEnd(); ++it) {
- memcpy(string_data + it.value(), it.key().constData(), it.key().size());
- string_data[it.value() + it.key().size()] = '\0';
- }
- }
+ char *string_data = new char[strings.blobSize()];
+ strings.writeBlob(string_data);
uint *uint_data = new uint[idata.size()];
memcpy(uint_data, idata.data(), idata.size() * sizeof(int));
@@ -499,7 +532,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
// put the metaobject together
obj->d.data = uint_data;
obj->d.extradata = 0;
- obj->d.stringdata = string_data;
+ obj->d.stringdata = reinterpret_cast<const QByteArrayData *>(string_data);
obj->d.superdata = &QDBusAbstractInterface::staticMetaObject;
}
@@ -613,22 +646,12 @@ static inline const QDBusMetaObjectPrivate *priv(const uint* data)
return reinterpret_cast<const QDBusMetaObjectPrivate *>(data);
}
-const char *QDBusMetaObject::dbusNameForMethod(int id) const
-{
- //id -= methodOffset();
- if (id >= 0 && id < priv(d.data)->methodCount) {
- int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
- return d.stringdata + d.data[handle];
- }
- return 0;
-}
-
const int *QDBusMetaObject::inputTypesForMethod(int id) const
{
//id -= methodOffset();
if (id >= 0 && id < priv(d.data)->methodCount) {
int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
- return reinterpret_cast<const int*>(d.data + d.data[handle + 1]);
+ return reinterpret_cast<const int*>(d.data + d.data[handle]);
}
return 0;
}
@@ -638,7 +661,7 @@ const int *QDBusMetaObject::outputTypesForMethod(int id) const
//id -= methodOffset();
if (id >= 0 && id < priv(d.data)->methodCount) {
int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
- return reinterpret_cast<const int*>(d.data + d.data[handle + 2]);
+ return reinterpret_cast<const int*>(d.data + d.data[handle + 1]);
}
return 0;
}
diff --git a/src/dbus/qdbusmetaobject_p.h b/src/dbus/qdbusmetaobject_p.h
index 7a8de41fa0..98d6105c72 100644
--- a/src/dbus/qdbusmetaobject_p.h
+++ b/src/dbus/qdbusmetaobject_p.h
@@ -71,12 +71,11 @@ struct Q_DBUS_EXPORT QDBusMetaObject: public QMetaObject
QDBusError &error);
~QDBusMetaObject()
{
- delete [] d.stringdata;
+ delete [] reinterpret_cast<const char *>(d.stringdata);
delete [] d.data;
}
// methods (slots & signals):
- const char *dbusNameForMethod(int id) const;
const int *inputTypesForMethod(int id) const;
const int *outputTypesForMethod(int id) const;
diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp
index b0d640608a..b5a138f654 100644
--- a/src/dbus/qdbusmetatype.cpp
+++ b/src/dbus/qdbusmetatype.cpp
@@ -49,11 +49,13 @@
#include <qreadwritelock.h>
#include <qvector.h>
-#include "qdbusmessage.h"
-#include "qdbusunixfiledescriptor.h"
-#include "qdbusutil_p.h"
#include "qdbusmetatype_p.h"
#include "qdbusargument_p.h"
+#include "qdbusutil_p.h"
+#include "qdbusunixfiledescriptor.h"
+#ifndef QT_BOOTSTRAPPED
+#include "qdbusmessage.h"
+#endif
#ifndef QT_NO_DBUS
@@ -111,13 +113,15 @@ void QDBusMetaTypeId::init()
// reentrancy is not a problem since everything else is locked on their own
// set the guard variable at the end
if (!initialized) {
+#ifndef QT_BOOTSTRAPPED
// register our types with QtCore
message = qRegisterMetaType<QDBusMessage>("QDBusMessage");
+ error = qRegisterMetaType<QDBusError>("QDBusError");
+#endif
argument = qRegisterMetaType<QDBusArgument>("QDBusArgument");
variant = qRegisterMetaType<QDBusVariant>("QDBusVariant");
objectpath = qRegisterMetaType<QDBusObjectPath>("QDBusObjectPath");
signature = qRegisterMetaType<QDBusSignature>("QDBusSignature");
- error = qRegisterMetaType<QDBusError>("QDBusError");
unixfd = qRegisterMetaType<QDBusUnixFileDescriptor>("QDBusUnixFileDescriptor");
#ifndef QDBUS_NO_SPECIALTYPES
@@ -150,6 +154,11 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
#endif
+#if QT_BOOTSTRAPPED
+ const int lastId = qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
+ message = lastId + 1;
+ error = lastId + 2;
+#endif
initialized = true;
}
}
@@ -290,9 +299,14 @@ bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
} else
df = info.demarshall;
}
-
+#ifndef QT_BOOTSTRAPPED
QDBusArgument copy = arg;
df(copy, data);
+#else
+ Q_UNUSED(arg);
+ Q_UNUSED(data);
+ Q_UNUSED(df);
+#endif
return true;
}
@@ -311,7 +325,7 @@ bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
int QDBusMetaType::signatureToType(const char *signature)
{
if (!signature)
- return QVariant::Invalid;
+ return QMetaType::UnknownType;
QDBusMetaTypeId::init();
switch (signature[0])
@@ -378,7 +392,7 @@ int QDBusMetaType::signatureToType(const char *signature)
}
// fall through
default:
- return QVariant::Invalid;
+ return QMetaType::UnknownType;
}
}
diff --git a/src/dbus/qdbusmisc.cpp b/src/dbus/qdbusmisc.cpp
index 7d68bf1185..fa9b74199e 100644
--- a/src/dbus/qdbusmisc.cpp
+++ b/src/dbus/qdbusmisc.cpp
@@ -41,14 +41,16 @@
#include <string.h>
+#ifndef QT_BOOTSTRAPPED
#include <QtCore/qcoreapplication.h>
#include <QtCore/qvariant.h>
#include <QtCore/qmetaobject.h>
#include "qdbusutil_p.h"
#include "qdbusconnection_p.h"
-#include "qdbusmetatype_p.h"
#include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_*
+#endif
+#include "qdbusmetatype_p.h"
#ifndef QT_NO_DBUS
@@ -69,6 +71,8 @@ bool qDBusCheckAsyncTag(const char *tag)
return false;
}
+#ifndef QT_BOOTSTRAPPED
+
QString qDBusInterfaceFromMetaObject(const QMetaObject *mo)
{
QString interface;
@@ -128,9 +132,14 @@ bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name)
// sig must be the normalised signature for the method
int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
{
- QDBusMetaTypeId::init();
+ return qDBusParametersForMethod(mm.parameterTypes(), metaTypes);
+}
+
+#endif // QT_BOOTSTRAPPED
- QList<QByteArray> parameterTypes = mm.parameterTypes();
+int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QList<int>& metaTypes)
+{
+ QDBusMetaTypeId::init();
metaTypes.clear();
metaTypes.append(0); // return type
@@ -141,7 +150,7 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
for ( ; it != end; ++it) {
const QByteArray &type = *it;
if (type.endsWith('*')) {
- //qWarning("Could not parse the method '%s'", mm.signature());
+ //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
// pointer?
return -1;
}
@@ -152,7 +161,7 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
int id = QMetaType::type(basictype);
if (id == 0) {
- //qWarning("Could not parse the method '%s'", mm.signature());
+ //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
// invalid type in method parameter list
return -1;
} else if (QDBusMetaType::typeToSignature(id) == 0)
@@ -164,14 +173,14 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
}
if (seenMessage) { // && !type.endsWith('&')
- //qWarning("Could not parse the method '%s'", mm.signature());
+ //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
// non-output parameters after message or after output params
return -1; // not allowed
}
int id = QMetaType::type(type);
- if (id == 0) {
- //qWarning("Could not parse the method '%s'", mm.signature());
+ if (id == QMetaType::UnknownType) {
+ //qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
// invalid type in method parameter list
return -1;
}
diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp
index 65d4b5533b..bb1bb76801 100644
--- a/src/dbus/qdbuspendingcall.cpp
+++ b/src/dbus/qdbuspendingcall.cpp
@@ -377,7 +377,7 @@ QDBusError QDBusPendingCall::error() const
{
if (d) {
QMutexLocker locker(&d->mutex);
- return d->replyMessage;
+ return QDBusError(d->replyMessage);
}
// not connected, return an error
diff --git a/src/dbus/qdbuspendingcall.h b/src/dbus/qdbuspendingcall.h
index 6dfdef59d0..8655435501 100644
--- a/src/dbus/qdbuspendingcall.h
+++ b/src/dbus/qdbuspendingcall.h
@@ -99,7 +99,7 @@ class Q_DBUS_EXPORT QDBusPendingCallWatcher: public QObject, public QDBusPending
{
Q_OBJECT
public:
- QDBusPendingCallWatcher(const QDBusPendingCall &call, QObject *parent = 0);
+ explicit QDBusPendingCallWatcher(const QDBusPendingCall &call, QObject *parent = 0);
~QDBusPendingCallWatcher();
#ifdef Q_QDOC
diff --git a/src/dbus/qdbuspendingcall_p.h b/src/dbus/qdbuspendingcall_p.h
index 2aaae7b494..eb0d9b6a11 100644
--- a/src/dbus/qdbuspendingcall_p.h
+++ b/src/dbus/qdbuspendingcall_p.h
@@ -125,7 +125,7 @@ public:
if (replyMessage.type() == QDBusMessage::ReplyMessage)
emit reply(replyMessage);
else
- emit error(replyMessage, sentMessage);
+ emit error(QDBusError(replyMessage), sentMessage);
emit finished();
}
diff --git a/src/dbus/qdbuspendingreply.h b/src/dbus/qdbuspendingreply.h
index ce8354deb3..0cdec7346d 100644
--- a/src/dbus/qdbuspendingreply.h
+++ b/src/dbus/qdbuspendingreply.h
@@ -132,9 +132,9 @@ public:
inline QDBusPendingReply(const QDBusPendingReply &other)
: QDBusPendingReplyData(other)
{ }
- inline QDBusPendingReply(const QDBusPendingCall &call)
+ inline /*implicit*/ QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
{ *this = call; }
- inline QDBusPendingReply(const QDBusMessage &message)
+ inline /*implicit*/ QDBusPendingReply(const QDBusMessage &message)
{ *this = message; }
inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
{ assign(other); return *this; }
diff --git a/src/dbus/qdbusreply.cpp b/src/dbus/qdbusreply.cpp
index 098fe7f4bb..c891874d98 100644
--- a/src/dbus/qdbusreply.cpp
+++ b/src/dbus/qdbusreply.cpp
@@ -186,7 +186,7 @@ QT_BEGIN_NAMESPACE
*/
void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data)
{
- error = reply;
+ error = QDBusError(reply);
if (error.isValid()) {
data = QVariant(); // clear it
diff --git a/src/dbus/qdbusreply.h b/src/dbus/qdbusreply.h
index a3170f7d54..8d40dd41d3 100644
--- a/src/dbus/qdbusreply.h
+++ b/src/dbus/qdbusreply.h
@@ -152,7 +152,7 @@ public:
}
inline QDBusReply& operator=(const QDBusMessage &reply)
{
- m_error = reply;
+ m_error = QDBusError(reply);
return *this;
}
inline QDBusReply(const QDBusError &dbusError = QDBusError())
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp
index bed07692b8..00141bb1cc 100644
--- a/src/dbus/qdbusutil.cpp
+++ b/src/dbus/qdbusutil.cpp
@@ -76,6 +76,7 @@ static inline bool isValidNumber(QChar c)
return (u >= '0' && u <= '9');
}
+#ifndef QT_BOOTSTRAPPED
static bool argToString(const QDBusArgument &arg, QString &out);
static bool variantToString(const QVariant &arg, QString &out)
@@ -237,6 +238,7 @@ bool argToString(const QDBusArgument &busArg, QString &out)
return true;
}
+#endif
//------- D-Bus Types --------
static const char oneLetterTypes[] = "vsogybnqiuxtdh";
@@ -319,7 +321,11 @@ namespace QDBusUtil
{
QString out;
+#ifndef QT_BOOTSTRAPPED
variantToString(arg, out);
+#else
+ Q_UNUSED(arg);
+#endif
return out;
}
diff --git a/src/dbus/qdbusxmlgenerator.cpp b/src/dbus/qdbusxmlgenerator.cpp
index a6572b2c86..550c82a0f2 100644
--- a/src/dbus/qdbusxmlgenerator.cpp
+++ b/src/dbus/qdbusxmlgenerator.cpp
@@ -126,7 +126,7 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
// now add methods:
for (int i = methodOffset; i < mo->methodCount(); ++i) {
QMetaMethod mm = mo->method(i);
- QByteArray signature = mm.signature();
+ QByteArray signature = mm.methodSignature();
int paren = signature.indexOf('(');
bool isSignal;
diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h
index af7dea5a6a..56a39b640d 100644
--- a/src/gui/accessible/qaccessible2.h
+++ b/src/gui/accessible/qaccessible2.h
@@ -115,7 +115,7 @@ public:
class Q_GUI_EXPORT QAccessibleSimpleEditableTextInterface: public QAccessibleEditableTextInterface
{
public:
- QAccessibleSimpleEditableTextInterface(QAccessibleInterface *accessibleInterface); //###
+ explicit QAccessibleSimpleEditableTextInterface(QAccessibleInterface *accessibleInterface); //###
void copyText(int startOffset, int endOffset) const;
void deleteText(int startOffset, int endOffset);
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index d3344c3a3a..db4ee242ff 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -78,10 +78,10 @@ QList<QByteArray> QAccessibleObjectPrivate::actionList() const
continue;
if (!qstrcmp(member.tag(), "QACCESSIBLE_SLOT")) {
- if (member.signature() == defaultAction)
+ if (member.methodSignature() == defaultAction)
actionList.prepend(defaultAction);
else
- actionList << member.signature();
+ actionList << member.methodSignature();
}
}
diff --git a/src/gui/image/qmovie.h b/src/gui/image/qmovie.h
index 9d4cb87b15..e11dea6ad3 100644
--- a/src/gui/image/qmovie.h
+++ b/src/gui/image/qmovie.h
@@ -83,7 +83,7 @@ public:
CacheAll
};
- QMovie(QObject *parent = 0);
+ explicit QMovie(QObject *parent = 0);
explicit QMovie(QIODevice *device, const QByteArray &format = QByteArray(), QObject *parent = 0);
explicit QMovie(const QString &fileName, const QByteArray &format = QByteArray(), QObject *parent = 0);
~QMovie();
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 3d78a43917..0b21be5c8e 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -67,10 +67,10 @@ public:
QPixmap();
explicit QPixmap(QPlatformPixmap *data);
QPixmap(int w, int h);
- QPixmap(const QSize &);
+ explicit QPixmap(const QSize &);
QPixmap(const QString& fileName, const char *format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor);
#ifndef QT_NO_IMAGEFORMAT_XPM
- QPixmap(const char * const xpm[]);
+ explicit QPixmap(const char * const xpm[]);
#endif
QPixmap(const QPixmap &);
~QPixmap();
diff --git a/src/gui/kernel/qclipboard.h b/src/gui/kernel/qclipboard.h
index 5a251dd0ef..5c88764d88 100644
--- a/src/gui/kernel/qclipboard.h
+++ b/src/gui/kernel/qclipboard.h
@@ -59,7 +59,7 @@ class Q_GUI_EXPORT QClipboard : public QObject
{
Q_OBJECT
private:
- QClipboard(QObject *parent);
+ explicit QClipboard(QObject *parent);
~QClipboard();
public:
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index e8ed5c0765..3e3db64d6f 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3625,7 +3625,7 @@ QTouchEvent::TouchPoint::TouchPoint(const QTouchEvent::TouchPoint &other)
*/
QTouchEvent::TouchPoint::~TouchPoint()
{
- if (!d->ref.deref())
+ if (d && !d->ref.deref())
delete d;
}
@@ -3867,10 +3867,11 @@ QTouchEvent::TouchPoint::InfoFlags QTouchEvent::TouchPoint::flags() const
}
/*!
+ \since 5.0
Returns the raw, unfiltered positions for the touch point. The positions are in native screen coordinates.
To get local coordinates you can use mapFromGlobal() of the QWindow returned by QTouchEvent::window().
- \note Returns an empty list if the touch device's capabilities do not include QTouchDevice::RawPositions.
+ \note Returns an empty vector if the touch device's capabilities do not include QTouchDevice::RawPositions.
\note Native screen coordinates refer to the native orientation of the screen which, in case of
mobile devices, is typically portrait. This means that on systems capable of screen orientation
@@ -3879,7 +3880,7 @@ QTouchEvent::TouchPoint::InfoFlags QTouchEvent::TouchPoint::flags() const
\sa QTouchDevice::capabilities(), device(), window()
*/
-QList<QPointF> QTouchEvent::TouchPoint::rawScreenPositions() const
+QVector<QPointF> QTouchEvent::TouchPoint::rawScreenPositions() const
{
return d->rawScreenPositions;
}
@@ -4037,7 +4038,7 @@ void QTouchEvent::TouchPoint::setVelocity(const QVector2D &v)
}
/*! \internal */
-void QTouchEvent::TouchPoint::setRawScreenPositions(const QList<QPointF> &positions)
+void QTouchEvent::TouchPoint::setRawScreenPositions(const QVector<QPointF> &positions)
{
if (d->ref.load() != 1)
d = d->detach();
@@ -4052,16 +4053,15 @@ void QTouchEvent::TouchPoint::setFlags(InfoFlags flags)
d->flags = flags;
}
-/*! \internal */
-QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::TouchPoint &other)
-{
- other.d->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = other.d;
- return *this;
-}
+/*!
+ \fn QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::TouchPoint &other)
+ \internal
+ */
+/*!
+ \fn void QTouchEvent::TouchPoint::swap(TouchPoint &other);
+ \internal
+*/
/*!
\class QScrollPrepareEvent
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index d70f6be201..a7dce43f72 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -713,9 +713,19 @@ public:
Q_DECLARE_FLAGS(InfoFlags, InfoFlag)
explicit TouchPoint(int id = -1);
- TouchPoint(const QTouchEvent::TouchPoint &other);
+ TouchPoint(const TouchPoint &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ TouchPoint(TouchPoint &&other) : d(other.d) { other.d = 0; }
+ TouchPoint &operator=(TouchPoint &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
~TouchPoint();
+ TouchPoint &operator=(const TouchPoint &other)
+ { if ( d != other.d ) { TouchPoint copy(other); swap(copy); } return *this; }
+
+ void swap(TouchPoint &other) { qSwap(d, other.d); }
+
int id() const;
Qt::TouchPointState state() const;
@@ -743,7 +753,7 @@ public:
qreal pressure() const;
QVector2D velocity() const;
InfoFlags flags() const;
- QList<QPointF> rawScreenPositions() const;
+ QVector<QPointF> rawScreenPositions() const;
// internal
void setId(int id);
@@ -766,8 +776,7 @@ public:
void setPressure(qreal pressure);
void setVelocity(const QVector2D &v);
void setFlags(InfoFlags flags);
- void setRawScreenPositions(const QList<QPointF> &positions);
- QTouchEvent::TouchPoint &operator=(const QTouchEvent::TouchPoint &other);
+ void setRawScreenPositions(const QVector<QPointF> &positions);
private:
QTouchEventTouchPointPrivate *d;
@@ -819,7 +828,7 @@ protected:
friend class QApplication;
friend class QApplicationPrivate;
};
-
+Q_DECLARE_TYPEINFO(QTouchEvent::TouchPoint, Q_MOVABLE_TYPE);
Q_DECLARE_OPERATORS_FOR_FLAGS(QTouchEvent::TouchPoint::InfoFlags)
class QScrollPrepareEventPrivate;
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 3f354c14e4..4c639f4eef 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -107,7 +107,7 @@ public:
qreal pressure;
QVector2D velocity;
QTouchEvent::TouchPoint::InfoFlags flags;
- QList<QPointF> rawScreenPositions;
+ QVector<QPointF> rawScreenPositions;
};
class QFileOpenEventPrivate
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 153b2b5c2d..b0200335d7 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -934,16 +934,6 @@ QKeySequence::QKeySequence()
Note the "File|Open" translator comment. It is by no means
necessary, but it provides some context for the human translator.
*/
-QKeySequence::QKeySequence(const QString &key)
-{
- d = new QKeySequencePrivate();
- assign(key);
-}
-
-/*!
- \since 4.7
- Creates a key sequence from the \a key string based on \a format.
-*/
QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat format)
{
d = new QKeySequencePrivate();
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index d1e7d06653..e8dd134bc3 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -146,8 +146,7 @@ public:
};
QKeySequence();
- QKeySequence(const QString &key);
- QKeySequence(const QString &key, SequenceFormat format);
+ QKeySequence(const QString &key, SequenceFormat format = NativeText);
QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0);
QKeySequence(const QKeySequence &ks);
QKeySequence(StandardKey key);
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 52f94a8a10..5e1cd17635 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -94,7 +94,7 @@ class Q_GUI_EXPORT QOpenGLContext : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QOpenGLContext)
public:
- QOpenGLContext(QObject *parent = 0);
+ explicit QOpenGLContext(QObject *parent = 0);
~QOpenGLContext();
void setFormat(const QSurfaceFormat &format);
diff --git a/src/gui/kernel/qplatformsharedgraphicscache_qpa.h b/src/gui/kernel/qplatformsharedgraphicscache_qpa.h
index d59cd7c3c8..f8ee201d85 100644
--- a/src/gui/kernel/qplatformsharedgraphicscache_qpa.h
+++ b/src/gui/kernel/qplatformsharedgraphicscache_qpa.h
@@ -65,7 +65,7 @@ public:
OpenGLTexture
};
- QPlatformSharedGraphicsCache(QObject *parent = 0) : QObject(parent) {}
+ explicit QPlatformSharedGraphicsCache(QObject *parent = 0) : QObject(parent) {}
Q_INVOKABLE virtual void ensureCacheInitialized(const QByteArray &cacheId, BufferType bufferType,
PixelFormat pixelFormat) = 0;
diff --git a/src/gui/kernel/qplatformsurface_qpa.h b/src/gui/kernel/qplatformsurface_qpa.h
index 76d5c5465c..80ee99c899 100644
--- a/src/gui/kernel/qplatformsurface_qpa.h
+++ b/src/gui/kernel/qplatformsurface_qpa.h
@@ -60,7 +60,7 @@ public:
QSurface::SurfaceClass surfaceClass() const;
private:
- QPlatformSurface(QSurface::SurfaceClass type);
+ explicit QPlatformSurface(QSurface::SurfaceClass type);
QSurface::SurfaceClass m_type;
diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h
index 170f62162f..a72de7b547 100644
--- a/src/gui/kernel/qplatformwindow_qpa.h
+++ b/src/gui/kernel/qplatformwindow_qpa.h
@@ -63,7 +63,7 @@ class Q_GUI_EXPORT QPlatformWindow : public QPlatformSurface
{
Q_DECLARE_PRIVATE(QPlatformWindow)
public:
- QPlatformWindow(QWindow *window);
+ explicit QPlatformWindow(QWindow *window);
virtual ~QPlatformWindow();
QWindow *window() const;
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index 111e10d340..3bd24db3ce 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -142,7 +142,7 @@ Q_SIGNALS:
void orientationChanged(Qt::ScreenOrientation orientation);
private:
- QScreen(QPlatformScreen *screen);
+ explicit QScreen(QPlatformScreen *screen);
Q_DISABLE_COPY(QScreen)
friend class QGuiApplicationPrivate;
diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h
index a8900fde33..befb771129 100644
--- a/src/gui/kernel/qsurface.h
+++ b/src/gui/kernel/qsurface.h
@@ -80,7 +80,7 @@ public:
virtual QSize size() const = 0;
protected:
- QSurface(SurfaceClass type);
+ explicit QSurface(SurfaceClass type);
SurfaceClass m_type;
diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h
index 6daa08095e..a4224bbedd 100644
--- a/src/gui/kernel/qsurfaceformat.h
+++ b/src/gui/kernel/qsurfaceformat.h
@@ -75,7 +75,7 @@ public:
};
QSurfaceFormat();
- QSurfaceFormat(FormatOptions options);
+ /*implicit*/ QSurfaceFormat(FormatOptions options);
QSurfaceFormat(const QSurfaceFormat &other);
QSurfaceFormat &operator=(const QSurfaceFormat &other);
~QSurfaceFormat();
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 1461f12520..62ddb66a75 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -94,8 +94,8 @@ class Q_GUI_EXPORT QWindow : public QObject, public QSurface
public:
- QWindow(QScreen *screen = 0);
- QWindow(QWindow *parent);
+ explicit QWindow(QScreen *screen = 0);
+ explicit QWindow(QWindow *parent);
virtual ~QWindow();
void setSurfaceType(SurfaceType surfaceType);
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h
index 6dae11ea81..040f62e763 100644
--- a/src/gui/kernel/qwindowsysteminterface_qpa.h
+++ b/src/gui/kernel/qwindowsysteminterface_qpa.h
@@ -98,7 +98,7 @@ public:
Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released}
QVector2D velocity; // in screen coordinate system, pixels / seconds
QTouchEvent::TouchPoint::InfoFlags flags;
- QList<QPointF> rawPositions; // in screen coordinates
+ QVector<QPointF> rawPositions; // in screen coordinates
};
static void registerTouchDevice(QTouchDevice *device);
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
index 0a2446587a..b987ab2334 100644
--- a/src/gui/math3d/qgenericmatrix.h
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -102,7 +102,7 @@ private:
#endif
T m[N][M]; // Column-major order to match OpenGL.
- QGenericMatrix(int) {} // Construct without initializing identity matrix.
+ explicit QGenericMatrix(int) {} // Construct without initializing identity matrix.
#if !defined(Q_NO_TEMPLATE_FRIENDS)
template <int NN, int MM, typename TT>
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index b80fc86f45..8353adfab1 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -201,7 +201,7 @@ private:
};
// Construct without initializing identity matrix.
- QMatrix4x4(int) { }
+ explicit QMatrix4x4(int) { }
QMatrix4x4 orthonormalInverse() const;
diff --git a/src/gui/opengl/qopenglframebufferobject.h b/src/gui/opengl/qopenglframebufferobject.h
index 63260f1940..9e69cecc58 100644
--- a/src/gui/opengl/qopenglframebufferobject.h
+++ b/src/gui/opengl/qopenglframebufferobject.h
@@ -67,7 +67,7 @@ public:
Depth
};
- QOpenGLFramebufferObject(const QSize &size, GLenum target = GL_TEXTURE_2D);
+ explicit QOpenGLFramebufferObject(const QSize &size, GLenum target = GL_TEXTURE_2D);
QOpenGLFramebufferObject(int width, int height, GLenum target = GL_TEXTURE_2D);
#if !defined(QT_OPENGL_ES) || defined(Q_QDOC)
QOpenGLFramebufferObject(const QSize &size, Attachment attachment,
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index 4e778dda66..ce36a821b6 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -198,7 +198,7 @@ class Q_GUI_EXPORT QOpenGLFunctions
{
public:
QOpenGLFunctions();
- QOpenGLFunctions(QOpenGLContext *context);
+ explicit QOpenGLFunctions(QOpenGLContext *context);
~QOpenGLFunctions() {}
enum OpenGLFeature
diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h
index ce3e7cf278..7d4b901fe7 100644
--- a/src/gui/opengl/qopenglpaintdevice.h
+++ b/src/gui/opengl/qopenglpaintdevice.h
@@ -71,7 +71,7 @@ class Q_GUI_EXPORT QOpenGLPaintDevice : public QPaintDevice
{
Q_DECLARE_PRIVATE(QOpenGLPaintDevice)
public:
- QOpenGLPaintDevice(const QSize &size);
+ explicit QOpenGLPaintDevice(const QSize &size);
QOpenGLPaintDevice(int width, int height);
virtual ~QOpenGLPaintDevice();
diff --git a/src/gui/painting/qbackingstore.h b/src/gui/painting/qbackingstore.h
index db6884f58d..ead15e7ea6 100644
--- a/src/gui/painting/qbackingstore.h
+++ b/src/gui/painting/qbackingstore.h
@@ -62,7 +62,7 @@ class QPlatformBackingStore;
class Q_GUI_EXPORT QBackingStore
{
public:
- QBackingStore(QWindow *window);
+ explicit QBackingStore(QWindow *window);
~QBackingStore();
QWindow *window() const;
diff --git a/src/gui/painting/qpdfwriter.h b/src/gui/painting/qpdfwriter.h
index 7b0547ad45..c617521369 100644
--- a/src/gui/painting/qpdfwriter.h
+++ b/src/gui/painting/qpdfwriter.h
@@ -57,8 +57,8 @@ class Q_GUI_EXPORT QPdfWriter : public QObject, public QPagedPaintDevice
{
Q_OBJECT
public:
- QPdfWriter(const QString &filename);
- QPdfWriter(QIODevice *device);
+ explicit QPdfWriter(const QString &filename);
+ explicit QPdfWriter(QIODevice *device);
~QPdfWriter();
QString title() const;
diff --git a/src/gui/painting/qplatformbackingstore_qpa.h b/src/gui/painting/qplatformbackingstore_qpa.h
index 8049c64c25..042913292f 100644
--- a/src/gui/painting/qplatformbackingstore_qpa.h
+++ b/src/gui/painting/qplatformbackingstore_qpa.h
@@ -62,7 +62,7 @@ class QPlatformWindow;
class Q_GUI_EXPORT QPlatformBackingStore
{
public:
- QPlatformBackingStore(QWindow *window);
+ explicit QPlatformBackingStore(QWindow *window);
virtual ~QPlatformBackingStore();
QWindow *window() const;
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index 0a089d3cf3..726ed434ed 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -61,9 +61,9 @@ class Q_GUI_EXPORT QPolygon : public QVector<QPoint>
public:
inline QPolygon() {}
inline ~QPolygon() {}
- inline QPolygon(int size);
+ inline explicit QPolygon(int size);
inline QPolygon(const QPolygon &a) : QVector<QPoint>(a) {}
- inline QPolygon(const QVector<QPoint> &v) : QVector<QPoint>(v) {}
+ inline /*implicit*/ QPolygon(const QVector<QPoint> &v) : QVector<QPoint>(v) {}
QPolygon(const QRect &r, bool closed=false);
QPolygon(int nPoints, const int *points);
inline void swap(QPolygon &other) { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps
@@ -135,11 +135,11 @@ class Q_GUI_EXPORT QPolygonF : public QVector<QPointF>
public:
inline QPolygonF() {}
inline ~QPolygonF() {}
- inline QPolygonF(int size);
+ inline explicit QPolygonF(int size);
inline QPolygonF(const QPolygonF &a) : QVector<QPointF>(a) {}
- inline QPolygonF(const QVector<QPointF> &v) : QVector<QPointF>(v) {}
+ inline /*implicit*/ QPolygonF(const QVector<QPointF> &v) : QVector<QPointF>(v) {}
QPolygonF(const QRectF &r);
- QPolygonF(const QPolygon &a);
+ /*implicit*/ QPolygonF(const QPolygon &a);
inline void swap(QPolygonF &other) { QVector<QPointF>::swap(other); } // prevent QVector<QPointF><->QPolygonF swaps
inline void translate(qreal dx, qreal dy);
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 9cc61198a5..cd1e3f0880 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -272,7 +272,7 @@ public:
inline void resolve(uint mask) { resolve_mask = mask; }
private:
- QFont(QFontPrivate *);
+ explicit QFont(QFontPrivate *);
void detach();
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 7209fbdfc3..fe9e1d16c7 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -535,7 +535,7 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
return qRound(width);
}
- QStackTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, QFont(d.data()));
layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -611,7 +611,7 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
int from = qMax(0, pos - 8);
int to = qMin(text.length(), pos + 8);
QString cstr = QString::fromRawData(text.unicode() + from, to - from);
- QStackTextEngine layout(cstr, d.data());
+ QStackTextEngine layout(cstr, QFont(d.data()));
layout.ignoreBidi = true;
layout.itemize();
width = qRound(layout.width(pos-from, 1));
@@ -660,7 +660,7 @@ QRect QFontMetrics::boundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QStackTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, QFont(d.data()));
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
@@ -830,7 +830,7 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QStackTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, QFont(d.data()));
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
@@ -1364,7 +1364,7 @@ qreal QFontMetricsF::width(const QString &text) const
int pos = text.indexOf(QLatin1Char('\x9c'));
int len = (pos != -1) ? pos : text.length();
- QStackTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, QFont(d.data()));
layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, len).toReal();
@@ -1441,7 +1441,7 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
if (len == 0)
return QRectF();
- QStackTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, QFont(d.data()));
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
@@ -1614,7 +1614,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QStackTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, QFont(d.data()));
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
diff --git a/src/gui/text/qsyntaxhighlighter.h b/src/gui/text/qsyntaxhighlighter.h
index 244f40b7ed..7107238a95 100644
--- a/src/gui/text/qsyntaxhighlighter.h
+++ b/src/gui/text/qsyntaxhighlighter.h
@@ -66,8 +66,8 @@ class Q_GUI_EXPORT QSyntaxHighlighter : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QSyntaxHighlighter)
public:
- QSyntaxHighlighter(QObject *parent);
- QSyntaxHighlighter(QTextDocument *parent);
+ explicit QSyntaxHighlighter(QObject *parent);
+ explicit QSyntaxHighlighter(QTextDocument *parent);
virtual ~QSyntaxHighlighter();
void setDocument(QTextDocument *doc);
diff --git a/src/gui/text/qtextdocumentwriter.h b/src/gui/text/qtextdocumentwriter.h
index c0dea06f8f..b7743b1ff7 100644
--- a/src/gui/text/qtextdocumentwriter.h
+++ b/src/gui/text/qtextdocumentwriter.h
@@ -59,7 +59,7 @@ class Q_GUI_EXPORT QTextDocumentWriter
public:
QTextDocumentWriter();
QTextDocumentWriter(QIODevice *device, const QByteArray &format);
- QTextDocumentWriter(const QString &fileName, const QByteArray &format = QByteArray());
+ explicit QTextDocumentWriter(const QString &fileName, const QByteArray &format = QByteArray());
~QTextDocumentWriter();
void setFormat (const QByteArray &format);
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 56098b0bdb..95b8f48ec5 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -340,7 +340,7 @@ QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *p
QFont f(font);
if (paintdevice)
f = QFont(font, paintdevice);
- d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d.data());
+ d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f);
}
/*!
diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h
index a0a4c76282..96a0cdda9b 100644
--- a/src/gui/text/qtextoption.h
+++ b/src/gui/text/qtextoption.h
@@ -86,7 +86,7 @@ public:
};
QTextOption();
- QTextOption(Qt::Alignment alignment);
+ /*implicit*/ QTextOption(Qt::Alignment alignment);
~QTextOption();
QTextOption(const QTextOption &o);
diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h
index f3191d2b1b..7aa8ad4091 100644
--- a/src/gui/util/qvalidator.h
+++ b/src/gui/util/qvalidator.h
@@ -176,7 +176,7 @@ class Q_GUI_EXPORT QRegExpValidator : public QValidator
public:
explicit QRegExpValidator(QObject *parent = 0);
- QRegExpValidator(const QRegExp& rx, QObject *parent = 0);
+ explicit QRegExpValidator(const QRegExp& rx, QObject *parent = 0);
~QRegExpValidator();
virtual QValidator::State validate(QString& input, int& pos) const;
diff --git a/src/network/access/qhttpmultipart.h b/src/network/access/qhttpmultipart.h
index c25beb7ae3..aea8421d30 100644
--- a/src/network/access/qhttpmultipart.h
+++ b/src/network/access/qhttpmultipart.h
@@ -92,8 +92,8 @@ public:
AlternativeType
};
- QHttpMultiPart(QObject *parent = 0);
- QHttpMultiPart(ContentType contentType, QObject *parent = 0);
+ explicit QHttpMultiPart(QObject *parent = 0);
+ explicit QHttpMultiPart(ContentType contentType, QObject *parent = 0);
~QHttpMultiPart();
void append(const QHttpPart &httpPart);
diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h
index 32307e305e..5553e857de 100644
--- a/src/network/access/qnetworkcookie.h
+++ b/src/network/access/qnetworkcookie.h
@@ -66,7 +66,7 @@ public:
Full
};
- QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray());
+ explicit QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray());
QNetworkCookie(const QNetworkCookie &other);
~QNetworkCookie();
QNetworkCookie &operator=(const QNetworkCookie &other);
diff --git a/src/network/access/qnetworkcookiejar.h b/src/network/access/qnetworkcookiejar.h
index 513fb3b66c..8e6fa45ac5 100644
--- a/src/network/access/qnetworkcookiejar.h
+++ b/src/network/access/qnetworkcookiejar.h
@@ -57,7 +57,7 @@ class Q_NETWORK_EXPORT QNetworkCookieJar: public QObject
{
Q_OBJECT
public:
- QNetworkCookieJar(QObject *parent = 0);
+ explicit QNetworkCookieJar(QObject *parent = 0);
virtual ~QNetworkCookieJar();
virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index b8d606c260..925ccab2b5 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -155,7 +155,7 @@ Q_SIGNALS:
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
protected:
- QNetworkReply(QObject *parent = 0);
+ explicit QNetworkReply(QObject *parent = 0);
QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent);
virtual qint64 writeData(const char *data, qint64 len);
diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h
index 198b19d8a8..89e8cbb852 100644
--- a/src/network/kernel/qdnslookup.h
+++ b/src/network/kernel/qdnslookup.h
@@ -191,7 +191,7 @@ public:
TXT = 16
};
- QDnsLookup(QObject *parent = 0);
+ explicit QDnsLookup(QObject *parent = 0);
QDnsLookup(Type type, const QString &name, QObject *parent = 0);
~QDnsLookup();
diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h
index df377872c8..2fc87f3bdc 100644
--- a/src/network/kernel/qhostinfo.h
+++ b/src/network/kernel/qhostinfo.h
@@ -63,7 +63,7 @@ public:
UnknownError
};
- QHostInfo(int lookupId = -1);
+ explicit QHostInfo(int lookupId = -1);
QHostInfo(const QHostInfo &d);
QHostInfo &operator=(const QHostInfo &d);
~QHostInfo();
diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h
index 805f5cdb5c..2e5c3ed687 100644
--- a/src/network/kernel/qnetworkproxy.h
+++ b/src/network/kernel/qnetworkproxy.h
@@ -68,10 +68,10 @@ public:
};
QNetworkProxyQuery();
- QNetworkProxyQuery(const QUrl &requestUrl, QueryType queryType = UrlRequest);
+ explicit QNetworkProxyQuery(const QUrl &requestUrl, QueryType queryType = UrlRequest);
QNetworkProxyQuery(const QString &hostname, int port, const QString &protocolTag = QString(),
QueryType queryType = TcpSocket);
- QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(),
+ explicit QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(),
QueryType queryType = TcpServer);
QNetworkProxyQuery(const QNetworkProxyQuery &other);
#ifndef QT_NO_BEARERMANAGEMENT
diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h
index 291122e10d..f9499c69ba 100644
--- a/src/network/socket/qlocalserver.h
+++ b/src/network/socket/qlocalserver.h
@@ -74,7 +74,7 @@ public:
};
Q_DECLARE_FLAGS(SocketOptions, SocketOption)
- QLocalServer(QObject *parent = 0);
+ explicit QLocalServer(QObject *parent = 0);
~QLocalServer();
void close();
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index b15d6e97bb..fbb38a9b46 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -82,8 +82,8 @@ public:
EmailAddress
};
- QSslCertificate(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem);
- QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem);
+ explicit QSslCertificate(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem);
+ explicit QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem);
QSslCertificate(const QSslCertificate &other);
~QSslCertificate();
QSslCertificate &operator=(const QSslCertificate &other);
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index aa16425e9a..f67ab5f25d 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -80,7 +80,7 @@ public:
AutoVerifyPeer
};
- QSslSocket(QObject *parent = 0);
+ explicit QSslSocket(QObject *parent = 0);
~QSslSocket();
void resume(); // to continue after proxy authentication required, SSL errors etc.
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
index a71a241ea6..7979e5d2d8 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -516,7 +516,7 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
{
QMutexLocker locker(&mutex);
- QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ QDBusPendingReply<QDBusObjectPath> reply(*watcher);
if (!reply.isError()) {
QDBusObjectPath result = reply.value();
diff --git a/src/printsupport/dialogs/qprintdialog.h b/src/printsupport/dialogs/qprintdialog.h
index 1eeca111e0..5bd832bcb0 100644
--- a/src/printsupport/dialogs/qprintdialog.h
+++ b/src/printsupport/dialogs/qprintdialog.h
@@ -63,7 +63,7 @@ class Q_PRINTSUPPORT_EXPORT QUnixPrintWidget : public QWidget
Q_OBJECT
public:
- QUnixPrintWidget(QPrinter *printer, QWidget *parent = 0);
+ explicit QUnixPrintWidget(QPrinter *printer, QWidget *parent = 0);
~QUnixPrintWidget();
void updatePrinter();
diff --git a/src/printsupport/kernel/qprinterinfo.h b/src/printsupport/kernel/qprinterinfo.h
index 64903bee85..d26b70dee0 100644
--- a/src/printsupport/kernel/qprinterinfo.h
+++ b/src/printsupport/kernel/qprinterinfo.h
@@ -59,7 +59,7 @@ class Q_PRINTSUPPORT_EXPORT QPrinterInfo
public:
QPrinterInfo();
QPrinterInfo(const QPrinterInfo &other);
- QPrinterInfo(const QPrinter &printer);
+ explicit QPrinterInfo(const QPrinter &printer);
~QPrinterInfo();
QPrinterInfo &operator=(const QPrinterInfo &other);
@@ -73,7 +73,7 @@ public:
static QPrinterInfo defaultPrinter();
private:
- QPrinterInfo(const QString &name);
+ explicit QPrinterInfo(const QString &name);
private:
friend class QPlatformPrinterSupport;
diff --git a/src/sql/kernel/qsqlfield.h b/src/sql/kernel/qsqlfield.h
index 58dce8b271..f5cda7ea64 100644
--- a/src/sql/kernel/qsqlfield.h
+++ b/src/sql/kernel/qsqlfield.h
@@ -57,8 +57,8 @@ class Q_SQL_EXPORT QSqlField
public:
enum RequiredStatus { Unknown = -1, Optional = 0, Required = 1 };
- QSqlField(const QString& fieldName = QString(),
- QVariant::Type type = QVariant::Invalid);
+ explicit QSqlField(const QString& fieldName = QString(),
+ QVariant::Type type = QVariant::Invalid);
QSqlField(const QSqlField& other);
QSqlField& operator=(const QSqlField& other);
diff --git a/src/sql/kernel/qsqlindex.h b/src/sql/kernel/qsqlindex.h
index e3e55b690e..0af63ab67c 100644
--- a/src/sql/kernel/qsqlindex.h
+++ b/src/sql/kernel/qsqlindex.h
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class Q_SQL_EXPORT QSqlIndex : public QSqlRecord
{
public:
- QSqlIndex(const QString &cursorName = QString(), const QString &name = QString());
+ explicit QSqlIndex(const QString &cursorName = QString(), const QString &name = QString());
QSqlIndex(const QSqlIndex &other);
~QSqlIndex();
QSqlIndex &operator=(const QSqlIndex &other);
diff --git a/src/sql/kernel/qsqlquery.h b/src/sql/kernel/qsqlquery.h
index 930bb25abf..19df1d52bb 100644
--- a/src/sql/kernel/qsqlquery.h
+++ b/src/sql/kernel/qsqlquery.h
@@ -62,8 +62,8 @@ class QSqlQueryPrivate;
class Q_SQL_EXPORT QSqlQuery
{
public:
- QSqlQuery(QSqlResult *r);
- QSqlQuery(const QString& query = QString(), QSqlDatabase db = QSqlDatabase());
+ explicit QSqlQuery(QSqlResult *r);
+ explicit QSqlQuery(const QString& query = QString(), QSqlDatabase db = QSqlDatabase());
explicit QSqlQuery(QSqlDatabase db);
QSqlQuery(const QSqlQuery& other);
QSqlQuery& operator=(const QSqlQuery& other);
diff --git a/src/testlib/qsignaldumper.cpp b/src/testlib/qsignaldumper.cpp
index 4fd870b644..c7b9f31b84 100644
--- a/src/testlib/qsignaldumper.cpp
+++ b/src/testlib/qsignaldumper.cpp
@@ -66,7 +66,7 @@ enum { IndentSpacesCount = 4 };
static QByteArray memberName(const QMetaMethod &member)
{
- QByteArray ba = member.signature();
+ QByteArray ba = member.methodSignature();
return ba.left(ba.indexOf('('));
}
@@ -112,7 +112,8 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv
quintptr addr = quintptr(*reinterpret_cast<void **>(argv[i + 1]));
str.append(QByteArray::number(addr, 16));
- } else if (typeId != QMetaType::Void) {
+ } else if (typeId != QMetaType::UnknownType) {
+ Q_ASSERT(typeId != QMetaType::Void); // void parameter => metaobject is corrupt
str.append(arg)
.append('(')
.append(QVariant(typeId, argv[i + 1]).toString().toLocal8Bit())
@@ -152,7 +153,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void **
str += QByteArray::number(quintptr(caller), 16);
str += ") ";
- str += member.signature();
+ str += member.methodSignature();
qPrintMessage(str);
}
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index eb52ebf706..70944baadf 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -122,9 +122,11 @@ private:
QList<QByteArray> params = member.parameterTypes();
for (int i = 0; i < params.count(); ++i) {
int tp = QMetaType::type(params.at(i).constData());
- if (tp == QMetaType::Void)
+ if (tp == QMetaType::UnknownType) {
+ Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
params.at(i).constData());
+ }
args << tp;
}
}
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index d167324aef..392e223e39 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -169,17 +169,13 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
-#ifndef QTEST_NO_SPECIALIZATIONS
template<>
-#endif
inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual,
const char *expected, const char *file, int line)
{
return qCompare<QString>(t1, QString(t2), actual, expected, file, line);
}
-#ifndef QTEST_NO_SPECIALIZATIONS
template<>
-#endif
inline bool qCompare(QLatin1String const &t1, QString const &t2, const char *actual,
const char *expected, const char *file, int line)
{
diff --git a/src/testlib/qtest_global.h b/src/testlib/qtest_global.h
index 27a6801db9..b567fe7c00 100644
--- a/src/testlib/qtest_global.h
+++ b/src/testlib/qtest_global.h
@@ -59,11 +59,6 @@ QT_BEGIN_NAMESPACE
# endif
#endif
-#if defined (Q_CC_SUN) || defined (Q_CC_XLC)
-# define QTEST_NO_SPECIALIZATIONS
-#endif
-
-
#if (defined Q_CC_HPACC) && (defined __ia64)
# ifdef Q_TESTLIB_EXPORT
# undef Q_TESTLIB_EXPORT
diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h
index f10ddd8473..24abd00e0f 100644
--- a/src/testlib/qtest_gui.h
+++ b/src/testlib/qtest_gui.h
@@ -88,9 +88,7 @@ inline bool qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const
}
#endif
-#ifndef QTEST_NO_SPECIALIZATIONS
template<>
-#endif
inline bool qCompare(QImage const &t1, QImage const &t2,
const char *actual, const char *expected, const char *file, int line)
{
@@ -125,9 +123,7 @@ inline bool qCompare(QImage const &t1, QImage const &t2,
toString(t1), toString(t2), actual, expected, file, line);
}
-#ifndef QTEST_NO_SPECIALIZATIONS
template<>
-#endif
inline bool qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, const char *expected,
const char *file, int line)
{
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 001a14a121..fb9a8e630c 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1067,7 +1067,8 @@ static bool isValidSlot(const QMetaMethod &sl)
if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty()
|| qstrlen(sl.typeName()) || sl.methodType() != QMetaMethod::Slot)
return false;
- const char *sig = sl.signature();
+ QByteArray signature = sl.methodSignature();
+ const char *sig = signature.constData();
int len = qstrlen(sig);
if (len < 2)
return false;
@@ -1090,7 +1091,7 @@ static void qPrintTestSlots(FILE *stream)
for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) {
QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
if (isValidSlot(sl))
- fprintf(stream, "%s\n", sl.signature());
+ fprintf(stream, "%s\n", sl.methodSignature().constData());
}
}
@@ -1115,7 +1116,7 @@ static void qPrintDataTags(FILE *stream)
// Retrieve local tags:
QStringList localTags;
QTestTable table;
- char *slot = qstrdup(tf.signature());
+ char *slot = qstrdup(tf.methodSignature().constData());
slot[strlen(slot) - 2] = '\0';
QByteArray member;
member.resize(qstrlen(slot) + qstrlen("_data()") + 1);
@@ -1787,7 +1788,7 @@ static void qInvokeTestMethods(QObject *testObject)
if (QTest::testFuncs) {
for (int i = 0; i != QTest::testFuncCount; i++) {
- if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).signature(),
+ if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).methodSignature().constData(),
QTest::testFuncs[i].data())) {
break;
}
@@ -1801,7 +1802,7 @@ static void qInvokeTestMethods(QObject *testObject)
for (int i = 0; i != methodCount; i++) {
if (!isValidSlot(testMethods[i]))
continue;
- if (!qInvokeTestMethod(testMethods[i].signature()))
+ if (!qInvokeTestMethod(testMethods[i].methodSignature().constData()))
break;
}
delete[] testMethods;
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index a344736f7b..acd494965e 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -256,7 +256,6 @@ namespace QTest
QTEST_COMPARE_DECL(bool)
#endif
-#ifndef QTEST_NO_SPECIALIZATIONS
template <typename T1, typename T2>
bool qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int);
@@ -312,34 +311,17 @@ namespace QTest
{
return compare_string_helper(t1, t2, actual, expected, file, line);
}
-#else /* QTEST_NO_SPECIALIZATIONS */
- inline bool qCompare(const char *t1, const char *t2, const char *actual,
- const char *expected, const char *file, int line)
- {
- return compare_string_helper(t1, t2, actual, expected, file, line);
- }
-
- inline bool qCompare(char *t1, char *t2, const char *actual, const char *expected,
- const char *file, int line)
- {
- return compare_string_helper(t1, t2, actual, expected, file, line);
- }
-#endif
/* The next two specializations are for MSVC that shows problems with implicit
conversions
*/
-#ifndef QTEST_NO_SPECIALIZATIONS
template<>
-#endif
inline bool qCompare(char *t1, const char *t2, const char *actual,
const char *expected, const char *file, int line)
{
return compare_string_helper(t1, t2, actual, expected, file, line);
}
-#ifndef QTEST_NO_SPECIALIZATIONS
template<>
-#endif
inline bool qCompare(const char *t1, char *t2, const char *actual,
const char *expected, const char *file, int line)
{
@@ -347,9 +329,7 @@ namespace QTest
}
// NokiaX86 and RVCT do not like implicitly comparing bool with int
-#ifndef QTEST_NO_SPECIALIZATIONS
template <>
-#endif
inline bool qCompare(bool const &t1, int const &t2,
const char *actual, const char *expected, const char *file, int line)
{
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index 5b70a5af64..9c34c758d7 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -63,6 +63,7 @@ SOURCES += \
../../corelib/io/qfsfileengine.cpp \
../../corelib/io/qfsfileengine_iterator.cpp \
../../corelib/io/qiodevice.cpp \
+ ../../corelib/io/qfiledevice.cpp \
../../corelib/io/qtemporaryfile.cpp \
../../corelib/io/qtextstream.cpp \
../../corelib/io/qurl.cpp \
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index ac602fd6e8..1284518fc5 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -54,30 +54,37 @@
QT_BEGIN_NAMESPACE
-uint qvariant_nameToType(const QByteArray &name)
+uint nameToBuiltinType(const QByteArray &name)
{
if (name.isEmpty())
return 0;
uint tp = QMetaType::type(name.constData());
- return tp < QMetaType::User ? tp : 0;
+ return tp < uint(QMetaType::User) ? tp : QMetaType::UnknownType;
}
/*
- Returns true if the type is a QVariant types.
+ Returns true if the type is a built-in type.
*/
-bool isVariantType(const QByteArray &type)
-{
- return qvariant_nameToType(type) != 0;
+bool isBuiltinType(const QByteArray &type)
+ {
+ int id = QMetaType::type(type.constData());
+ if (id == QMetaType::UnknownType)
+ return false;
+ return (id < QMetaType::User);
}
-/*!
- Returns true if the type is qreal.
-*/
-static bool isQRealType(const QByteArray &type)
-{
- return (type == "qreal");
-}
+static const char *metaTypeEnumValueString(int type)
+ {
+#define RETURN_METATYPENAME_STRING(MetaTypeName, MetaTypeId, RealType) \
+ case QMetaType::MetaTypeName: return #MetaTypeName;
+
+ switch (type) {
+QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
+ }
+#undef RETURN_METATYPENAME_STRING
+ return 0;
+ }
Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile)
: out(outfile), cdef(classDef), metaTypes(metaTypes)
@@ -109,24 +116,28 @@ static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
return i - startPos;
}
-int Generator::strreg(const QByteArray &s)
+void Generator::strreg(const QByteArray &s)
{
- int idx = 0;
- for (int i = 0; i < strings.size(); ++i) {
- const QByteArray &str = strings.at(i);
- if (str == s)
- return idx;
- idx += str.length() + 1;
- for (int i = 0; i < str.length(); ++i) {
- if (str.at(i) == '\\') {
- int cnt = lengthOfEscapeSequence(str, i) - 1;
- idx -= cnt;
- i += cnt;
- }
- }
- }
- strings.append(s);
- return idx;
+ if (!strings.contains(s))
+ strings.append(s);
+}
+
+int Generator::stridx(const QByteArray &s)
+{
+ int i = strings.indexOf(s);
+ Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings");
+ return i;
+}
+
+// Returns the sum of all parameters (including return type) for the given
+// \a list of methods. This is needed for calculating the size of the methods'
+// parameter type/name meta-data.
+static int aggregateParameterCount(const QList<FunctionDef> &list)
+{
+ int sum = 0;
+ for (int i = 0; i < list.count(); ++i)
+ sum += list.at(i).arguments.count() + 1; // +1 for return type
+ return sum;
}
void Generator::generateCode()
@@ -135,10 +146,6 @@ void Generator::generateCode()
bool isQObject = (cdef->classname == "QObject");
bool isConstructible = !cdef->constructorList.isEmpty();
-//
-// build the data array
-//
-
// filter out undeclared enumerators and sets
{
QList<EnumDef> enumList;
@@ -156,15 +163,119 @@ void Generator::generateCode()
cdef->enumList = enumList;
}
+//
+// Register all strings used in data section
+//
+ strreg(cdef->qualified);
+ registerClassInfoStrings();
+ registerFunctionStrings(cdef->signalList);
+ registerFunctionStrings(cdef->slotList);
+ registerFunctionStrings(cdef->methodList);
+ registerFunctionStrings(cdef->constructorList);
+ registerPropertyStrings();
+ registerEnumStrings();
QByteArray qualifiedClassNameIdentifier = cdef->qualified;
qualifiedClassNameIdentifier.replace(':', '_');
+//
+// Build stringdata struct
+//
+ fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
+ fprintf(out, " QByteArrayData data[%d];\n", strings.size());
+ {
+ int len = 0;
+ for (int i = 0; i < strings.size(); ++i)
+ len += strings.at(i).length() + 1;
+ fprintf(out, " char stringdata[%d];\n", len + 1);
+ }
+ fprintf(out, "};\n");
+
+ // Macro that expands into a QByteArrayData. The offset member is
+ // calculated from 1) the offset of the actual characters in the
+ // stringdata.stringdata member, and 2) the stringdata.data index of the
+ // QByteArrayData being defined. This calculation relies on the
+ // QByteArrayData::data() implementation returning simply "this + offset".
+ fprintf(out, "#define QT_MOC_LITERAL(idx, ofs, len) { \\\n"
+ " Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \\\n"
+ " offsetof(qt_meta_stringdata_%s_t, stringdata) + ofs \\\n"
+ " - idx * sizeof(QByteArrayData) \\\n"
+ " }\n",
+ qualifiedClassNameIdentifier.constData());
+
+ fprintf(out, "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n",
+ qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
+ fprintf(out, " {\n");
+ {
+ int idx = 0;
+ for (int i = 0; i < strings.size(); ++i) {
+ if (i)
+ fprintf(out, ",\n");
+ const QByteArray &str = strings.at(i);
+ fprintf(out, "QT_MOC_LITERAL(%d, %d, %d)", i, idx, str.length());
+ idx += str.length() + 1;
+ for (int j = 0; j < str.length(); ++j) {
+ if (str.at(j) == '\\') {
+ int cnt = lengthOfEscapeSequence(str, j) - 1;
+ idx -= cnt;
+ j += cnt;
+ }
+ }
+ }
+ fprintf(out, "\n },\n");
+ }
+
+//
+// Build stringdata array
+//
+ fprintf(out, " \"");
+ int col = 0;
+ int len = 0;
+ for (int i = 0; i < strings.size(); ++i) {
+ QByteArray s = strings.at(i);
+ len = s.length();
+ if (col && col + len >= 72) {
+ fprintf(out, "\"\n \"");
+ col = 0;
+ } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
+ fprintf(out, "\"\"");
+ len += 2;
+ }
+ int idx = 0;
+ while (idx < s.length()) {
+ if (idx > 0) {
+ col = 0;
+ fprintf(out, "\"\n \"");
+ }
+ int spanLen = qMin(70, s.length() - idx);
+ // don't cut escape sequences at the end of a line
+ int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
+ if (backSlashPos >= idx) {
+ int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
+ spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
+ }
+ fwrite(s.constData() + idx, 1, spanLen, out);
+ idx += spanLen;
+ col += spanLen;
+ }
+
+ fputs("\\0", out);
+ col += len + 2;
+ }
+
+// Terminate stringdata struct
+ fprintf(out, "\"\n};\n");
+ fprintf(out, "#undef QT_MOC_LITERAL\n\n");
+
+//
+// build the data array
+//
+
int index = MetaObjectPrivateFieldCount;
fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
fprintf(out, "\n // content:\n");
fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision));
- fprintf(out, " %4d, // classname\n", strreg(cdef->qualified));
+ fprintf(out, " %4d, // classname\n", stridx(cdef->qualified));
fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
index += cdef->classInfoList.count() * 2;
@@ -173,6 +284,15 @@ void Generator::generateCode()
index += methodCount * 5;
if (cdef->revisionedMethods)
index += methodCount;
+ int paramsIndex = index;
+ int totalParameterCount = aggregateParameterCount(cdef->signalList)
+ + aggregateParameterCount(cdef->slotList)
+ + aggregateParameterCount(cdef->methodList)
+ + aggregateParameterCount(cdef->constructorList);
+ index += totalParameterCount * 2 // types and parameter names
+ - methodCount // return "parameters" don't have names
+ - cdef->constructorList.count(); // "this" parameters don't have names
+
fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0);
index += cdef->propertyList.count() * 3;
if(cdef->notifyableProperties)
@@ -199,17 +319,17 @@ void Generator::generateCode()
//
// Build signals array first, otherwise the signal indices would be wrong
//
- generateFunctions(cdef->signalList, "signal", MethodSignal);
+ generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex);
//
// Build slots array
//
- generateFunctions(cdef->slotList, "slot", MethodSlot);
+ generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex);
//
// Build method array
//
- generateFunctions(cdef->methodList, "method", MethodMethod);
+ generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex);
//
// Build method version arrays
@@ -221,6 +341,15 @@ void Generator::generateCode()
}
//
+// Build method parameters array
+//
+ generateFunctionParameters(cdef->signalList, "signal");
+ generateFunctionParameters(cdef->slotList, "slot");
+ generateFunctionParameters(cdef->methodList, "method");
+ if (isConstructible)
+ generateFunctionParameters(cdef->constructorList, "constructor");
+
+//
// Build property array
//
generateProperties();
@@ -234,7 +363,7 @@ void Generator::generateCode()
// Build constructors array
//
if (isConstructible)
- generateFunctions(cdef->constructorList, "constructor", MethodConstructor);
+ generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex);
//
// Terminate data array
@@ -242,46 +371,6 @@ void Generator::generateCode()
fprintf(out, "\n 0 // eod\n};\n\n");
//
-// Build stringdata array
-//
- fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData());
- fprintf(out, " \"");
- int col = 0;
- int len = 0;
- for (int i = 0; i < strings.size(); ++i) {
- QByteArray s = strings.at(i);
- len = s.length();
- if (col && col + len >= 72) {
- fprintf(out, "\"\n \"");
- col = 0;
- } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
- fprintf(out, "\"\"");
- len += 2;
- }
- int idx = 0;
- while (idx < s.length()) {
- if (idx > 0) {
- col = 0;
- fprintf(out, "\"\n \"");
- }
- int spanLen = qMin(70, s.length() - idx);
- // don't cut escape sequences at the end of a line
- int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
- if (backSlashPos >= idx) {
- int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
- spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
- }
- fwrite(s.constData() + idx, 1, spanLen, out);
- idx += spanLen;
- col += spanLen;
- }
-
- fputs("\\0", out);
- col += len + 2;
- }
- fprintf(out, "\"\n};\n\n");
-
-//
// Generate internal qt_static_metacall() function
//
if (cdef->hasQObject && !isQt)
@@ -293,7 +382,7 @@ void Generator::generateCode()
QList<QByteArray> extraList;
for (int i = 0; i < cdef->propertyList.count(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
- if (!isVariantType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
+ if (!isBuiltinType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
!p.type.contains('<') && !p.type.contains('>')) {
int s = p.type.lastIndexOf("::");
if (s > 0) {
@@ -356,8 +445,9 @@ void Generator::generateCode()
fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData());
else
fprintf(out, " { 0, ");
- fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ",
- qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
+ fprintf(out, "qt_meta_stringdata_%s.data,\n"
+ " qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(),
+ qualifiedClassNameIdentifier.constData());
if (!hasExtraData)
fprintf(out, "0 }\n");
else
@@ -379,7 +469,7 @@ void Generator::generateCode()
//
fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
fprintf(out, " if (!_clname) return 0;\n");
- fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s))\n"
+ fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n"
" return static_cast<void*>(const_cast< %s*>(this));\n",
qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
@@ -430,6 +520,15 @@ void Generator::generateCode()
}
+void Generator::registerClassInfoStrings()
+{
+ for (int i = 0; i < cdef->classInfoList.size(); ++i) {
+ const ClassInfoDef &c = cdef->classInfoList.at(i);
+ strreg(c.name);
+ strreg(c.value);
+ }
+}
+
void Generator::generateClassInfos()
{
if (cdef->classInfoList.isEmpty())
@@ -439,32 +538,37 @@ void Generator::generateClassInfos()
for (int i = 0; i < cdef->classInfoList.size(); ++i) {
const ClassInfoDef &c = cdef->classInfoList.at(i);
- fprintf(out, " %4d, %4d,\n", strreg(c.name), strreg(c.value));
+ fprintf(out, " %4d, %4d,\n", stridx(c.name), stridx(c.value));
}
}
-void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type)
+void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
{
- if (list.isEmpty())
- return;
- fprintf(out, "\n // %ss: signature, parameters, type, tag, flags\n", functype);
-
for (int i = 0; i < list.count(); ++i) {
const FunctionDef &f = list.at(i);
- QByteArray sig = f.name + '(';
- QByteArray arguments;
+ strreg(f.name);
+ if (!isBuiltinType(f.normalizedType))
+ strreg(f.normalizedType);
+ strreg(f.tag);
for (int j = 0; j < f.arguments.count(); ++j) {
const ArgumentDef &a = f.arguments.at(j);
- if (j) {
- sig += ",";
- arguments += ",";
- }
- sig += a.normalizedType;
- arguments += a.name;
+ if (!isBuiltinType(a.normalizedType))
+ strreg(a.normalizedType);
+ strreg(a.name);
}
- sig += ')';
+ }
+}
+
+void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type, int &paramsIndex)
+{
+ if (list.isEmpty())
+ return;
+ fprintf(out, "\n // %ss: name, argc, parameters, tag, flags\n", functype);
+
+ for (int i = 0; i < list.count(); ++i) {
+ const FunctionDef &f = list.at(i);
unsigned char flags = type;
if (f.access == FunctionDef::Private)
@@ -487,8 +591,12 @@ void Generator::generateFunctions(const QList<FunctionDef>& list, const char *fu
flags |= MethodScriptable;
if (f.revision > 0)
flags |= MethodRevisioned;
- fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig),
- strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags);
+
+ int argc = f.arguments.count();
+ fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n",
+ stridx(f.name), argc, paramsIndex, stridx(f.tag), flags);
+
+ paramsIndex += 1 + argc * 2;
}
}
@@ -502,6 +610,54 @@ void Generator::generateFunctionRevisions(const QList<FunctionDef>& list, const
}
}
+void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const char *functype)
+{
+ if (list.isEmpty())
+ return;
+ fprintf(out, "\n // %ss: parameters\n", functype);
+ for (int i = 0; i < list.count(); ++i) {
+ const FunctionDef &f = list.at(i);
+ fprintf(out, " ");
+
+ // Types
+ for (int j = -1; j < f.arguments.count(); ++j) {
+ if (j > -1)
+ fputc(' ', out);
+ const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
+ if (isBuiltinType(typeName)) {
+ int type = nameToBuiltinType(typeName);
+ const char *valueString = metaTypeEnumValueString(type);
+ if (valueString)
+ fprintf(out, "QMetaType::%s", valueString);
+ else
+ fprintf(out, "%4d", type);
+ } else {
+ Q_ASSERT(!typeName.isEmpty() || f.isConstructor);
+ fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(typeName));
+ }
+ fputc(',', out);
+ }
+
+ // Parameter names
+ for (int j = 0; j < f.arguments.count(); ++j) {
+ const ArgumentDef &arg = f.arguments.at(j);
+ fprintf(out, " %4d,", stridx(arg.name));
+ }
+
+ fprintf(out, "\n");
+ }
+}
+
+void Generator::registerPropertyStrings()
+{
+ for (int i = 0; i < cdef->propertyList.count(); ++i) {
+ const PropertyDef &p = cdef->propertyList.at(i);
+ strreg(p.name);
+ if (!isBuiltinType(p.type))
+ strreg(p.type);
+ }
+}
+
void Generator::generateProperties()
{
//
@@ -513,11 +669,8 @@ void Generator::generateProperties()
for (int i = 0; i < cdef->propertyList.count(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
uint flags = Invalid;
- if (!isVariantType(p.type)) {
+ if (!isBuiltinType(p.type))
flags |= EnumOrFlag;
- } else if (!isQRealType(p.type)) {
- flags |= qvariant_nameToType(p.type) << 24;
- }
if (!p.read.isEmpty())
flags |= Readable;
if (!p.write.isEmpty()) {
@@ -567,12 +720,20 @@ void Generator::generateProperties()
if (p.final)
flags |= Final;
- fprintf(out, " %4d, %4d, ",
- strreg(p.name),
- strreg(p.type));
- if (!(flags >> 24) && isQRealType(p.type))
- fprintf(out, "(QMetaType::QReal << 24) | ");
- fprintf(out, "0x%.8x,\n", flags);
+ fprintf(out, " %4d, ", stridx(p.name));
+
+ if (isBuiltinType(p.type)) {
+ int type = nameToBuiltinType(p.type);
+ const char *valueString = metaTypeEnumValueString(type);
+ if (valueString)
+ fprintf(out, "QMetaType::%s", valueString);
+ else
+ fprintf(out, "%4d", type);
+ } else {
+ fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(p.type));
+ }
+
+ fprintf(out, ", 0x%.8x,\n", flags);
}
if(cdef->notifyableProperties) {
@@ -596,6 +757,16 @@ void Generator::generateProperties()
}
}
+void Generator::registerEnumStrings()
+{
+ for (int i = 0; i < cdef->enumList.count(); ++i) {
+ const EnumDef &e = cdef->enumList.at(i);
+ strreg(e.name);
+ for (int j = 0; j < e.values.count(); ++j)
+ strreg(e.values.at(j));
+ }
+}
+
void Generator::generateEnums(int index)
{
if (cdef->enumDeclarations.isEmpty())
@@ -607,7 +778,7 @@ void Generator::generateEnums(int index)
for (i = 0; i < cdef->enumList.count(); ++i) {
const EnumDef &e = cdef->enumList.at(i);
fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n",
- strreg(e.name),
+ stridx(e.name),
cdef->enumDeclarations.value(e.name) ? 1 : 0,
e.values.count(),
index);
@@ -624,7 +795,7 @@ void Generator::generateEnums(int index)
code += "::" + e.name;
code += "::" + val;
fprintf(out, " %4d, uint(%s),\n",
- strreg(val), code.constData());
+ stridx(val), code.constData());
}
}
}
@@ -926,8 +1097,9 @@ void Generator::generateStaticMetacall()
fprintf(out, " switch (_id) {\n");
for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
const FunctionDef &f = methodList.at(methodindex);
+ Q_ASSERT(!f.normalizedType.isEmpty());
fprintf(out, " case %d: ", methodindex);
- if (f.normalizedType.size())
+ if (f.normalizedType != "void")
fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData());
fprintf(out, "_t->");
if (f.inPrivateClass.size())
@@ -942,7 +1114,7 @@ void Generator::generateStaticMetacall()
isUsed_a = true;
}
fprintf(out, ");");
- if (f.normalizedType.size()) {
+ if (f.normalizedType != "void") {
fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
noRef(f.normalizedType).constData());
isUsed_a = true;
@@ -1021,7 +1193,8 @@ void Generator::generateSignal(FunctionDef *def,int index)
constQualifier = "const";
}
- if (def->arguments.isEmpty() && def->normalizedType.isEmpty()) {
+ Q_ASSERT(!def->normalizedType.isEmpty());
+ if (def->arguments.isEmpty() && def->normalizedType == "void") {
fprintf(out, ")%s\n{\n"
" QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n"
"}\n", constQualifier, thisPtr.constData(), index);
@@ -1036,11 +1209,11 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "%s _t%d%s", a.type.name.constData(), offset++, a.rightType.constData());
}
fprintf(out, ")%s\n{\n", constQualifier);
- if (def->type.name.size() && def->normalizedType.size())
+ if (def->type.name.size() && def->normalizedType != "void")
fprintf(out, " %s _t0 = %s();\n", noRef(def->normalizedType).constData(), noRef(def->normalizedType).constData());
fprintf(out, " void *_a[] = { ");
- if (def->normalizedType.isEmpty()) {
+ if (def->normalizedType == "void") {
fprintf(out, "0");
} else {
if (def->returnTypeIsVolatile)
@@ -1056,7 +1229,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i);
fprintf(out, " };\n");
fprintf(out, " QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index);
- if (def->normalizedType.size())
+ if (def->normalizedType != "void")
fprintf(out, " return _t0;\n");
fprintf(out, "}\n");
}
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 46eee4ca06..c85d24fd15 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -55,17 +55,23 @@ public:
Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile = 0);
void generateCode();
private:
+ void registerClassInfoStrings();
void generateClassInfos();
- void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type);
+ void registerFunctionStrings(const QList<FunctionDef> &list);
+ void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type, int &paramsIndex);
void generateFunctionRevisions(const QList<FunctionDef>& list, const char *functype);
+ void generateFunctionParameters(const QList<FunctionDef> &list, const char *functype);
+ void registerEnumStrings();
void generateEnums(int index);
+ void registerPropertyStrings();
void generateProperties();
void generateMetacall();
void generateStaticMetacall();
void generateSignal(FunctionDef *def, int index);
void generatePluginMetaData();
- int strreg(const QByteArray &); // registers a string and returns its id
+ void strreg(const QByteArray &); // registers a string
+ int stridx(const QByteArray &); // returns a string's id
QList<QByteArray> strings;
QByteArray purestSuperClass;
QList<QByteArray> metaTypes;
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 4189c29de1..e85aadbba7 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -75,9 +75,7 @@ static QByteArray normalizeType(const QByteArray &ba, bool fixScope = false)
}
}
*d = '\0';
- QByteArray result;
- if (strncmp("void", buf, d - buf) != 0)
- result = normalizeTypeInternal(buf, d, fixScope);
+ QByteArray result = normalizeTypeInternal(buf, d, fixScope);
if (buf != stackbuf)
delete [] buf;
return result;
@@ -822,8 +820,8 @@ void Moc::generate(FILE *out)
if (classList.size() && classList.first().classname == "Qt")
fprintf(out, "#include <QtCore/qobject.h>\n");
- if (mustIncludeQMetaTypeH)
- fprintf(out, "#include <QtCore/qmetatype.h>\n");
+ fprintf(out, "#include <QtCore/qbytearray.h>\n"); // For QByteArrayData
+ fprintf(out, "#include <QtCore/qmetatype.h>\n"); // For QMetaType::Type
if (mustIncludeQPluginH)
fprintf(out, "#include <QtCore/qplugin.h>\n");
@@ -981,8 +979,6 @@ void Moc::createPropertyDef(PropertyDef &propDef)
type = "qlonglong";
else if (type == "ULongLong")
type = "qulonglong";
- else if (type == "qreal")
- mustIncludeQMetaTypeH = true;
propDef.type = type;
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 9e9225da0a..b12ec492ff 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -200,7 +200,7 @@ class Moc : public Parser
public:
Moc(Preprocessor &p)
: preprocessor(p), noInclude(false), generatedCode(false),
- mustIncludeQMetaTypeH(false), mustIncludeQPluginH(false)
+ mustIncludeQPluginH(false)
{}
QByteArray filename;
@@ -208,7 +208,6 @@ public:
Preprocessor &preprocessor;
bool noInclude;
bool generatedCode;
- bool mustIncludeQMetaTypeH;
bool mustIncludeQPluginH;
QByteArray includePath;
QList<QByteArray> includeFiles;
diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h
index 2ce5b9b765..cff0f98fca 100644
--- a/src/tools/moc/outputrevision.h
+++ b/src/tools/moc/outputrevision.h
@@ -43,6 +43,6 @@
#define OUTPUTREVISION_H
// if the output revision changes, you MUST change it in qobjectdefs.h too
-enum { mocOutputRevision = 64 }; // moc format output revision
+enum { mocOutputRevision = 65 }; // moc format output revision
#endif // OUTPUTREVISION_H
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index 07986a71e6..696b32c728 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -937,10 +937,15 @@ Symbols Preprocessor::preprocessed(const QByteArray &filename, FILE *file)
{
QFile qfile;
qfile.open(file, QFile::ReadOnly);
- QByteArray input = qfile.readAll();
+ return preprocessed(filename, &qfile);
+}
+
+Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file)
+{
+ QByteArray input = file->readAll();
if (input.isEmpty())
return symbols;
-
+
// phase 1: get rid of backslash-newlines
input = cleaned(input);
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index e0707da4ee..4e0bd6343d 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -62,6 +62,7 @@ typedef SubArray MacroName;
typedef QHash<MacroName, Macro> Macros;
typedef QVector<MacroName> MacroSafeSet;
+class QIODevice;
class Preprocessor : public Parser
{
@@ -80,6 +81,7 @@ public:
QSet<QByteArray> preprocessedIncludes;
Macros macros;
Symbols preprocessed(const QByteArray &filename, FILE *file);
+ Symbols preprocessed(const QByteArray &filename, QIODevice *device);
void skipUntilEndif();
diff --git a/src/widgets/dialogs/qdialog.h b/src/widgets/dialogs/qdialog.h
index 7d3052a782..f20ff46d41 100644
--- a/src/widgets/dialogs/qdialog.h
+++ b/src/widgets/dialogs/qdialog.h
@@ -91,8 +91,8 @@ Q_SIGNALS:
void rejected();
public Q_SLOTS:
- void open();
- int exec();
+ virtual void open();
+ virtual int exec();
virtual void done(int);
virtual void accept();
virtual void reject();
diff --git a/src/widgets/itemviews/qcolumnview_p.h b/src/widgets/itemviews/qcolumnview_p.h
index 5bdb74c56c..c3c79d35a3 100644
--- a/src/widgets/itemviews/qcolumnview_p.h
+++ b/src/widgets/itemviews/qcolumnview_p.h
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
class QColumnViewPreviewColumn : public QAbstractItemView {
public:
- QColumnViewPreviewColumn(QWidget *parent) : QAbstractItemView(parent), previewWidget(0) {
+ explicit QColumnViewPreviewColumn(QWidget *parent) : QAbstractItemView(parent), previewWidget(0) {
}
void setPreviewWidget(QWidget *widget) {
diff --git a/src/widgets/itemviews/qdatawidgetmapper.h b/src/widgets/itemviews/qdatawidgetmapper.h
index e73d4b1044..3cb8f09510 100644
--- a/src/widgets/itemviews/qdatawidgetmapper.h
+++ b/src/widgets/itemviews/qdatawidgetmapper.h
@@ -66,7 +66,7 @@ class Q_WIDGETS_EXPORT QDataWidgetMapper: public QObject
Q_PROPERTY(SubmitPolicy submitPolicy READ submitPolicy WRITE setSubmitPolicy)
public:
- QDataWidgetMapper(QObject *parent = 0);
+ explicit QDataWidgetMapper(QObject *parent = 0);
~QDataWidgetMapper();
void setModel(QAbstractItemModel *model);
diff --git a/src/widgets/itemviews/qitemeditorfactory.h b/src/widgets/itemviews/qitemeditorfactory.h
index aff8de3a4c..8bc1cc7df6 100644
--- a/src/widgets/itemviews/qitemeditorfactory.h
+++ b/src/widgets/itemviews/qitemeditorfactory.h
@@ -69,7 +69,7 @@ template <class T>
class QItemEditorCreator : public QItemEditorCreatorBase
{
public:
- inline QItemEditorCreator(const QByteArray &valuePropertyName);
+ inline explicit QItemEditorCreator(const QByteArray &valuePropertyName);
inline QWidget *createWidget(QWidget *parent) const { return new T(parent); }
inline QByteArray valuePropertyName() const { return propertyName; }
diff --git a/src/widgets/itemviews/qstandarditemmodel.h b/src/widgets/itemviews/qstandarditemmodel.h
index e374665f20..767665fd94 100644
--- a/src/widgets/itemviews/qstandarditemmodel.h
+++ b/src/widgets/itemviews/qstandarditemmodel.h
@@ -66,7 +66,7 @@ class Q_WIDGETS_EXPORT QStandardItem
{
public:
QStandardItem();
- QStandardItem(const QString &text);
+ explicit QStandardItem(const QString &text);
QStandardItem(const QIcon &icon, const QString &text);
explicit QStandardItem(int rows, int columns = 1);
virtual ~QStandardItem();
diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h
index 3d08e204d1..0c6ed85fc9 100644
--- a/src/widgets/itemviews/qtablewidget.h
+++ b/src/widgets/itemviews/qtablewidget.h
@@ -84,7 +84,7 @@ class Q_WIDGETS_EXPORT QTableWidgetItem
friend class QTableModel;
public:
enum ItemType { Type = 0, UserType = 1000 };
- QTableWidgetItem(int type = Type);
+ explicit QTableWidgetItem(int type = Type);
explicit QTableWidgetItem(const QString &text, int type = Type);
explicit QTableWidgetItem(const QIcon &icon, const QString &text, int type = Type);
QTableWidgetItem(const QTableWidgetItem &other);
diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h
index c9654d3e8e..c5f1032728 100644
--- a/src/widgets/itemviews/qtreewidget.h
+++ b/src/widgets/itemviews/qtreewidget.h
@@ -69,7 +69,7 @@ class Q_WIDGETS_EXPORT QTreeWidgetItem
public:
enum ItemType { Type = 0, UserType = 1000 };
explicit QTreeWidgetItem(int type = Type);
- QTreeWidgetItem(const QStringList &strings, int type = Type);
+ explicit QTreeWidgetItem(const QStringList &strings, int type = Type);
explicit QTreeWidgetItem(QTreeWidget *view, int type = Type);
QTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type = Type);
QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int type = Type);
diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp
index 9b40063e65..0d2e7716e5 100644
--- a/src/widgets/kernel/qstackedlayout.cpp
+++ b/src/widgets/kernel/qstackedlayout.cpp
@@ -477,6 +477,38 @@ void QStackedLayout::setGeometry(const QRect &rect)
}
/*!
+ \reimp
+*/
+bool QStackedLayout::hasHeightForWidth() const
+{
+ const int n = count();
+
+ for (int i = 0; i < n; ++i) {
+ if (QLayoutItem *item = itemAt(i)) {
+ if (item->hasHeightForWidth())
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+int QStackedLayout::heightForWidth(int width) const
+{
+ const int n = count();
+
+ int hfw = 0;
+ for (int i = 0; i < n; ++i) {
+ if (QLayoutItem *item = itemAt(i)) {
+ hfw = qMax(hfw, item->heightForWidth(width));
+ }
+ }
+ return hfw;
+}
+
+/*!
\enum QStackedLayout::StackingMode
\since 4.4
diff --git a/src/widgets/kernel/qstackedlayout.h b/src/widgets/kernel/qstackedlayout.h
index e54efa886e..fa77341c52 100644
--- a/src/widgets/kernel/qstackedlayout.h
+++ b/src/widgets/kernel/qstackedlayout.h
@@ -94,6 +94,8 @@ public:
QLayoutItem *itemAt(int) const;
QLayoutItem *takeAt(int);
void setGeometry(const QRect &rect);
+ bool hasHeightForWidth() const;
+ int heightForWidth(int width) const;
Q_SIGNALS:
void widgetRemoved(int index);
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index a4bb205b76..ffb4b1fef5 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -8404,6 +8404,7 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event)
void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
+ Q_UNUSED(event);
}
#ifndef QT_NO_WHEELEVENT
diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp
index 9617d6de58..5406f5dcf5 100644
--- a/src/widgets/widgets/qstackedwidget.cpp
+++ b/src/widgets/widgets/qstackedwidget.cpp
@@ -49,54 +49,12 @@
QT_BEGIN_NAMESPACE
-/**
- QStackedLayout does not support height for width (simply because it does not reimplement
- heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking
- binary compatibility. (QLayout is subject to multiple inheritance).
- However, we can fix QStackedWidget by simply using a modified version of QStackedLayout
- that reimplements the hfw-related functions:
- */
-class QStackedLayoutHFW : public QStackedLayout
-{
-public:
- QStackedLayoutHFW(QWidget *parent = 0) : QStackedLayout(parent) {}
- bool hasHeightForWidth() const;
- int heightForWidth(int width) const;
-};
-
-bool QStackedLayoutHFW::hasHeightForWidth() const
-{
- const int n = count();
-
- for (int i = 0; i < n; ++i) {
- if (QLayoutItem *item = itemAt(i)) {
- if (item->hasHeightForWidth())
- return true;
- }
- }
- return false;
-}
-
-int QStackedLayoutHFW::heightForWidth(int width) const
-{
- const int n = count();
-
- int hfw = 0;
- for (int i = 0; i < n; ++i) {
- if (QLayoutItem *item = itemAt(i)) {
- hfw = qMax(hfw, item->heightForWidth(width));
- }
- }
- return hfw;
-}
-
-
class QStackedWidgetPrivate : public QFramePrivate
{
Q_DECLARE_PUBLIC(QStackedWidget)
public:
QStackedWidgetPrivate():layout(0){}
- QStackedLayoutHFW *layout;
+ QStackedLayout *layout;
bool blockChildAdd;
};
@@ -180,7 +138,7 @@ QStackedWidget::QStackedWidget(QWidget *parent)
: QFrame(*new QStackedWidgetPrivate, parent)
{
Q_D(QStackedWidget);
- d->layout = new QStackedLayoutHFW(this);
+ d->layout = new QStackedLayout(this);
connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int)));
connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int)));
}
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 84c32e519b..2cc573e958 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -429,7 +429,7 @@ void QTabBarPrivate::layoutTabs()
tabList[i].maxRect = QRect(x, 0, sz.width(), sz.height());
x += sz.width();
maxHeight = qMax(maxHeight, sz.height());
- sz = minimumTabSizeHint(i);
+ sz = q->minimumTabSizeHint(i);
tabList[i].minRect = QRect(minx, 0, sz.width(), sz.height());
minx += sz.width();
tabChain[tabChainIndex].init();
@@ -454,7 +454,7 @@ void QTabBarPrivate::layoutTabs()
tabList[i].maxRect = QRect(0, y, sz.width(), sz.height());
y += sz.height();
maxWidth = qMax(maxWidth, sz.width());
- sz = minimumTabSizeHint(i);
+ sz = q->minimumTabSizeHint(i);
tabList[i].minRect = QRect(0, miny, sz.width(), sz.height());
miny += sz.height();
tabChain[tabChainIndex].init();
@@ -1294,14 +1294,18 @@ static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
return ret;
}
-QSize QTabBarPrivate::minimumTabSizeHint(int index)
+/*!
+ Returns the minimum tab size hint for the tab at position \a index.
+ \since Qt 5.0
+*/
+
+QSize QTabBar::minimumTabSizeHint(int index) const
{
- Q_Q(QTabBar);
- // ### Qt 5: make this a protected virtual function in QTabBar
- Tab &tab = tabList[index];
+ Q_D(const QTabBar);
+ QTabBarPrivate::Tab &tab = const_cast<QTabBarPrivate::Tab&>(d->tabList[index]);
QString oldText = tab.text;
- tab.text = computeElidedText(elideMode, oldText);
- QSize size = q->tabSizeHint(index);
+ tab.text = computeElidedText(d->elideMode, oldText);
+ QSize size = tabSizeHint(index);
tab.text = oldText;
return size;
}
diff --git a/src/widgets/widgets/qtabbar.h b/src/widgets/widgets/qtabbar.h
index 85586f5e57..2698213d07 100644
--- a/src/widgets/widgets/qtabbar.h
+++ b/src/widgets/widgets/qtabbar.h
@@ -178,6 +178,7 @@ Q_SIGNALS:
protected:
virtual QSize tabSizeHint(int index) const;
+ virtual QSize minimumTabSizeHint(int index) const;
virtual void tabInserted(int index);
virtual void tabRemoved(int index);
virtual void tabLayoutChange();
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index c907b48eeb..aa9db38677 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -165,8 +165,6 @@ public:
inline bool validIndex(int index) const { return index >= 0 && index < tabList.count(); }
void setCurrentNextEnabledIndex(int offset);
- QSize minimumTabSizeHint(int index);
-
QToolButton* rightB; // right or bottom
QToolButton* leftB; // left or top
diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h
index 86d0956290..038b0c750f 100644
--- a/src/xml/sax/qxml.h
+++ b/src/xml/sax/qxml.h
@@ -158,7 +158,7 @@ class Q_XML_EXPORT QXmlInputSource
{
public:
QXmlInputSource();
- QXmlInputSource(QIODevice *dev);
+ explicit QXmlInputSource(QIODevice *dev);
virtual ~QXmlInputSource();
virtual void setData(const QString& dat);
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index a74d817b8a..3bff330db2 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -262,9 +262,16 @@ void tst_QUrl::hashInPath()
QCOMPARE(withHashInPath.path(), QString::fromLatin1("hi#mum.txt"));
QCOMPARE(withHashInPath.toEncoded(), QByteArray("hi%23mum.txt"));
QCOMPARE(withHashInPath.toString(), QString("hi%23mum.txt"));
+ QCOMPARE(withHashInPath.toDisplayString(QUrl::PreferLocalFile), QString("hi%23mum.txt"));
QUrl fromHashInPath = QUrl::fromEncoded(withHashInPath.toEncoded());
QVERIFY(withHashInPath == fromHashInPath);
+
+ const QUrl localWithHash = QUrl::fromLocalFile("/hi#mum.txt");
+ QCOMPARE(localWithHash.path(), QString::fromLatin1("/hi#mum.txt"));
+ QCOMPARE(localWithHash.toEncoded(), QByteArray("file:///hi%23mum.txt"));
+ QCOMPARE(localWithHash.toString(), QString("file:///hi%23mum.txt"));
+ QCOMPARE(localWithHash.toDisplayString(QUrl::PreferLocalFile), QString("/hi#mum.txt"));
}
void tst_QUrl::unc()
@@ -352,6 +359,7 @@ void tst_QUrl::setUrl()
QCOMPARE(url.port(), -1);
QCOMPARE(url.toString(), QString::fromLatin1("file:///"));
QCOMPARE(url.toDisplayString(), QString::fromLatin1("file:///"));
+ QCOMPARE(url.toDisplayString(QUrl::PreferLocalFile), QString::fromLatin1("/"));
}
{
@@ -367,6 +375,7 @@ void tst_QUrl::setUrl()
QCOMPARE(url.port(), 80);
QCOMPARE(url.toString(), QString::fromLatin1("http://www.foo.bar:80"));
QCOMPARE(url.toDisplayString(), QString::fromLatin1("http://www.foo.bar:80"));
+ QCOMPARE(url.toDisplayString(QUrl::PreferLocalFile), QString::fromLatin1("http://www.foo.bar:80"));
QUrl url2("//www1.foo.bar");
QCOMPARE(url.resolved(url2).toString(), QString::fromLatin1("http://www1.foo.bar"));
@@ -451,15 +460,7 @@ void tst_QUrl::setUrl()
QUrl url = u1;
QVERIFY(url.isValid());
QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my#myref"));
- QCOMPARE(url.fragment(), QString::fromLatin1("myref"));
- }
-
- {
- QString u1 = "file:/home/dfaure/my#myref";
- QUrl url = u1;
- QVERIFY(url.isValid());
-
- QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my#myref"));
+ QCOMPARE(url.toString(QUrl::PreferLocalFile), QString::fromLatin1("file:///home/dfaure/my#myref"));
QCOMPARE(url.fragment(), QString::fromLatin1("myref"));
}
@@ -1001,6 +1002,7 @@ void tst_QUrl::toLocalFile()
QUrl url(theUrl);
QCOMPARE(url.toLocalFile(), theFile);
+ QCOMPARE(url.isLocalFile(), !theFile.isEmpty());
}
void tst_QUrl::fromLocalFile_data()
diff --git a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
index 1651d00738..f44a671180 100644
--- a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
+++ b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
@@ -223,7 +223,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject()")
<< QByteArray("MethodTestObject()")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>())
<< (QList<QByteArray>())
<< (QList<QByteArray>())
@@ -259,7 +259,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(int)")
<< QByteArray("MethodTestObject(int)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>() << int(QMetaType::Int))
<< (QList<QByteArray>() << QByteArray("int"))
<< (QList<QByteArray>() << QByteArray("constructorIntArg"))
@@ -295,7 +295,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(qreal)")
<< QByteArray("MethodTestObject(qreal)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>() << qMetaTypeId<qreal>())
<< (QList<QByteArray>() << QByteArray("qreal"))
<< (QList<QByteArray>() << QByteArray("constructorQRealArg"))
@@ -331,7 +331,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(QString)")
<< QByteArray("MethodTestObject(QString)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>() << int(QMetaType::QString))
<< (QList<QByteArray>() << QByteArray("QString"))
<< (QList<QByteArray>() << QByteArray("constructorQStringArg"))
@@ -367,7 +367,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(CustomType)")
<< QByteArray("MethodTestObject(CustomType)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>() << qMetaTypeId<CustomType>())
<< (QList<QByteArray>() << QByteArray("CustomType"))
<< (QList<QByteArray>() << QByteArray("constructorCustomTypeArg"))
@@ -403,7 +403,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(CustomUnregisteredType)")
<< QByteArray("MethodTestObject(CustomUnregisteredType)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>() << 0)
<< (QList<QByteArray>() << QByteArray("CustomUnregisteredType"))
<< (QList<QByteArray>() << QByteArray("constructorCustomUnregisteredTypeArg"))
@@ -536,7 +536,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)")
<< QByteArray("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< parameterTypes << parameterTypeNames << parameterNames
<< QMetaMethod::Public
<< QMetaMethod::Constructor;
@@ -571,7 +571,7 @@ void tst_QMetaMethod::method_data()
QTest::newRow("MethodTestObject(bool,int)")
<< QByteArray("MethodTestObject(bool,int)")
- << int(QMetaType::Void) << QByteArray("")
+ << int(QMetaType::UnknownType) << QByteArray("")
<< (QList<int>() << int(QMetaType::Bool) << int(QMetaType::Int))
<< (QList<QByteArray>() << QByteArray("bool") << QByteArray("int"))
<< (QList<QByteArray>() << QByteArray("") << QByteArray(""))
@@ -603,15 +603,50 @@ void tst_QMetaMethod::method()
QCOMPARE(method.methodType(), methodType);
QCOMPARE(method.access(), access);
- QCOMPARE(method.signature(), signature.constData());
+ QVERIFY(!method.methodSignature().isEmpty());
+ if (method.methodSignature() != signature) {
+ // QMetaMethod should always produce a semantically equivalent signature
+ int signatureIndex = (methodType == QMetaMethod::Constructor)
+ ? mo->indexOfConstructor(method.methodSignature())
+ : mo->indexOfMethod(method.methodSignature());
+ QCOMPARE(signatureIndex, index);
+ }
- QCOMPARE(method.tag(), "");
+ QByteArray computedName = signature.left(signature.indexOf('('));
+ QCOMPARE(method.name(), computedName);
- QCOMPARE(method.typeName(), returnTypeName.constData());
- QCOMPARE(QMetaType::type(method.typeName()), returnType);
+ QCOMPARE(method.tag(), "");
+ QCOMPARE(method.returnType(), returnType);
+ if (QByteArray(method.typeName()) != returnTypeName) {
+ // QMetaMethod should always produce a semantically equivalent typename
+ QCOMPARE(QMetaType::type(method.typeName()), QMetaType::type(returnTypeName));
+ }
- QCOMPARE(method.parameterTypes(), parameterTypeNames);
+ if (method.parameterTypes() != parameterTypeNames) {
+ // QMetaMethod should always produce semantically equivalent typenames
+ QList<QByteArray> actualTypeNames = method.parameterTypes();
+ QCOMPARE(actualTypeNames.size(), parameterTypeNames.size());
+ for (int i = 0; i < parameterTypeNames.size(); ++i) {
+ QCOMPARE(QMetaType::type(actualTypeNames.at(i)),
+ QMetaType::type(parameterTypeNames.at(i)));
+ }
+ }
QCOMPARE(method.parameterNames(), parameterNames);
+
+ QCOMPARE(method.parameterCount(), parameterTypes.size());
+ for (int i = 0; i < parameterTypes.size(); ++i)
+ QCOMPARE(method.parameterType(i), parameterTypes.at(i));
+
+ {
+ QVector<int> actualParameterTypes(parameterTypes.size());
+ method.getParameterTypes(actualParameterTypes.data());
+ for (int i = 0; i < parameterTypes.size(); ++i)
+ QCOMPARE(actualParameterTypes.at(i), parameterTypes.at(i));
+ }
+
+ // Bogus indexes
+ QCOMPARE(method.parameterType(-1), 0);
+ QCOMPARE(method.parameterType(parameterTypes.size()), 0);
}
void tst_QMetaMethod::invalidMethod()
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 09fd0a7adb..b6b68338cd 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -978,25 +978,25 @@ void tst_QMetaObject::propertyNotify()
QVERIFY(prop.isValid());
QVERIFY(prop.hasNotifySignal());
QMetaMethod signal = prop.notifySignal();
- QCOMPARE(signal.signature(), "value6Changed()");
+ QCOMPARE(signal.methodSignature(), QByteArray("value6Changed()"));
prop = mo->property(mo->indexOfProperty("value7"));
QVERIFY(prop.isValid());
QVERIFY(prop.hasNotifySignal());
signal = prop.notifySignal();
- QCOMPARE(signal.signature(), "value7Changed(QString)");
+ QCOMPARE(signal.methodSignature(), QByteArray("value7Changed(QString)"));
prop = mo->property(mo->indexOfProperty("value8"));
QVERIFY(prop.isValid());
QVERIFY(!prop.hasNotifySignal());
signal = prop.notifySignal();
- QCOMPARE(signal.signature(), (const char *)0);
+ QCOMPARE(signal.methodSignature(), QByteArray());
prop = mo->property(mo->indexOfProperty("value"));
QVERIFY(prop.isValid());
QVERIFY(!prop.hasNotifySignal());
signal = prop.notifySignal();
- QCOMPARE(signal.signature(), (const char *)0);
+ QCOMPARE(signal.methodSignature(), QByteArray());
}
void tst_QMetaObject::propertyConstant()
@@ -1114,7 +1114,7 @@ void tst_QMetaObject::indexOfMethod()
QFETCH(bool, isSignal);
int idx = object->metaObject()->indexOfMethod(name);
QVERIFY(idx >= 0);
- QCOMPARE(object->metaObject()->method(idx).signature(), name.constData());
+ QCOMPARE(object->metaObject()->method(idx).methodSignature(), name);
QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx);
QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx);
}
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 97b14a374e..f187425c84 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -217,6 +217,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(nullMethod.signature(), QByteArray());
QVERIFY(nullMethod.methodType() == QMetaMethod::Method);
QVERIFY(nullMethod.returnType().isEmpty());
+ QVERIFY(nullMethod.parameterTypes().isEmpty());
QVERIFY(nullMethod.parameterNames().isEmpty());
QVERIFY(nullMethod.tag().isEmpty());
QVERIFY(nullMethod.access() == QMetaMethod::Public);
@@ -229,6 +230,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(method1.methodType() == QMetaMethod::Method);
QVERIFY(method1.returnType().isEmpty());
+ QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QVERIFY(method1.parameterNames().isEmpty());
QVERIFY(method1.tag().isEmpty());
QVERIFY(method1.access() == QMetaMethod::Public);
@@ -242,6 +244,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
QVERIFY(method2.methodType() == QMetaMethod::Method);
QCOMPARE(method2.returnType(), QByteArray("int"));
+ QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
QVERIFY(method2.parameterNames().isEmpty());
QVERIFY(method2.tag().isEmpty());
QVERIFY(method2.access() == QMetaMethod::Public);
@@ -267,6 +270,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(method1.methodType() == QMetaMethod::Method);
QCOMPARE(method1.returnType(), QByteArray("int"));
+ QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
QCOMPARE(method1.tag(), QByteArray("tag"));
QVERIFY(method1.access() == QMetaMethod::Private);
@@ -276,6 +280,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
QVERIFY(method2.methodType() == QMetaMethod::Method);
QCOMPARE(method2.returnType(), QByteArray("int"));
+ QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
QVERIFY(method2.parameterNames().isEmpty());
QVERIFY(method2.tag().isEmpty());
QVERIFY(method2.access() == QMetaMethod::Public);
@@ -296,6 +301,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(method1.methodType() == QMetaMethod::Method);
QCOMPARE(method1.returnType(), QByteArray("int"));
+ QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
QCOMPARE(method1.tag(), QByteArray("tag"));
QVERIFY(method1.access() == QMetaMethod::Private);
@@ -305,6 +311,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
QVERIFY(method2.methodType() == QMetaMethod::Method);
QCOMPARE(method2.returnType(), QByteArray("QString"));
+ QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
QVERIFY(method2.access() == QMetaMethod::Protected);
@@ -320,6 +327,7 @@ void tst_QMetaObjectBuilder::method()
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
QVERIFY(method2.methodType() == QMetaMethod::Method);
QCOMPARE(method2.returnType(), QByteArray("QString"));
+ QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
QVERIFY(method2.access() == QMetaMethod::Protected);
@@ -347,6 +355,7 @@ void tst_QMetaObjectBuilder::slot()
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(method1.methodType() == QMetaMethod::Slot);
QVERIFY(method1.returnType().isEmpty());
+ QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QVERIFY(method1.parameterNames().isEmpty());
QVERIFY(method1.tag().isEmpty());
QVERIFY(method1.access() == QMetaMethod::Public);
@@ -359,6 +368,7 @@ void tst_QMetaObjectBuilder::slot()
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
QVERIFY(method2.methodType() == QMetaMethod::Slot);
QVERIFY(method2.returnType().isEmpty());
+ QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
QVERIFY(method2.parameterNames().isEmpty());
QVERIFY(method2.tag().isEmpty());
QVERIFY(method2.access() == QMetaMethod::Public);
@@ -384,6 +394,7 @@ void tst_QMetaObjectBuilder::signal()
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(method1.methodType() == QMetaMethod::Signal);
QVERIFY(method1.returnType().isEmpty());
+ QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QVERIFY(method1.parameterNames().isEmpty());
QVERIFY(method1.tag().isEmpty());
QVERIFY(method1.access() == QMetaMethod::Protected);
@@ -396,6 +407,7 @@ void tst_QMetaObjectBuilder::signal()
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
QVERIFY(method2.methodType() == QMetaMethod::Signal);
QVERIFY(method2.returnType().isEmpty());
+ QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
QVERIFY(method2.parameterNames().isEmpty());
QVERIFY(method2.tag().isEmpty());
QVERIFY(method2.access() == QMetaMethod::Protected);
@@ -421,6 +433,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
QVERIFY(ctor1.returnType().isEmpty());
+ QCOMPARE(ctor1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QVERIFY(ctor1.parameterNames().isEmpty());
QVERIFY(ctor1.tag().isEmpty());
QVERIFY(ctor1.access() == QMetaMethod::Public);
@@ -433,6 +446,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
QVERIFY(ctor2.returnType().isEmpty());
+ QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
QVERIFY(ctor2.parameterNames().isEmpty());
QVERIFY(ctor2.tag().isEmpty());
QVERIFY(ctor2.access() == QMetaMethod::Public);
@@ -458,6 +472,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
QCOMPARE(ctor1.returnType(), QByteArray("int"));
+ QCOMPARE(ctor1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
QCOMPARE(ctor1.tag(), QByteArray("tag"));
QVERIFY(ctor1.access() == QMetaMethod::Private);
@@ -466,6 +481,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
QVERIFY(ctor2.returnType().isEmpty());
+ QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
QVERIFY(ctor2.parameterNames().isEmpty());
QVERIFY(ctor2.tag().isEmpty());
QVERIFY(ctor2.access() == QMetaMethod::Public);
@@ -484,6 +500,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
QCOMPARE(ctor1.returnType(), QByteArray("int"));
+ QCOMPARE(ctor1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
QCOMPARE(ctor1.tag(), QByteArray("tag"));
QVERIFY(ctor1.access() == QMetaMethod::Private);
@@ -492,6 +509,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
QCOMPARE(ctor2.returnType(), QByteArray("QString"));
+ QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
QVERIFY(ctor2.access() == QMetaMethod::Protected);
@@ -506,6 +524,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
QCOMPARE(ctor2.returnType(), QByteArray("QString"));
+ QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
QVERIFY(ctor2.access() == QMetaMethod::Protected);
@@ -525,6 +544,7 @@ void tst_QMetaObjectBuilder::constructor()
QCOMPARE(prototypeConstructor.signature(), QByteArray("SomethingOfEverything()"));
QVERIFY(prototypeConstructor.methodType() == QMetaMethod::Constructor);
QCOMPARE(prototypeConstructor.returnType(), QByteArray());
+ QVERIFY(prototypeConstructor.parameterTypes().isEmpty());
QVERIFY(prototypeConstructor.access() == QMetaMethod::Public);
QCOMPARE(prototypeConstructor.index(), 1);
@@ -1161,12 +1181,15 @@ bool tst_QMetaObjectBuilder::checkForSideEffects
static bool sameMethod(const QMetaMethod& method1, const QMetaMethod& method2)
{
- if (QByteArray(method1.signature()) != QByteArray(method2.signature()))
+ if (method1.methodSignature() != method2.methodSignature())
return false;
if (QByteArray(method1.typeName()) != QByteArray(method2.typeName()))
return false;
+ if (method1.parameterTypes() != method2.parameterTypes())
+ return false;
+
if (method1.parameterNames() != method2.parameterNames())
return false;
@@ -1466,7 +1489,7 @@ void TestObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;
default: {
QMetaMethod ctor = _o->metaObject()->constructor(_id);
- qFatal("You forgot to add a case for CreateInstance %s", ctor.signature());
+ qFatal("You forgot to add a case for CreateInstance %s", ctor.methodSignature().constData());
}
}
} else if (_c == QMetaObject::InvokeMetaMethod) {
@@ -1478,7 +1501,7 @@ void TestObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
case 2: *reinterpret_cast<QVariantList(*)>(_a[0]) = _t->listInvokableQRealQString(*reinterpret_cast<qreal(*)>(_a[1]), *reinterpret_cast<QString(*)>(_a[2])); break;
default: {
QMetaMethod method = _o->metaObject()->method(_o->metaObject()->methodOffset() + _id);
- qFatal("You forgot to add a case for InvokeMetaMethod %s", method.signature());
+ qFatal("You forgot to add a case for InvokeMetaMethod %s", method.methodSignature().constData());
}
}
} else if (_c == QMetaObject::IndexOfMethod) {
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index a3959f6d33..96c391d582 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -101,12 +101,29 @@ private slots:
struct Foo { int i; };
+
+class CustomQObject : public QObject
+{
+ Q_OBJECT
+public:
+ CustomQObject(QObject *parent = 0)
+ : QObject(parent)
+ {
+ }
+};
+
+class CustomNonQObject {};
+
void tst_QMetaType::defined()
{
QCOMPARE(int(QMetaTypeId2<QString>::Defined), 1);
QCOMPARE(int(QMetaTypeId2<Foo>::Defined), 0);
QCOMPARE(int(QMetaTypeId2<void*>::Defined), 1);
QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0);
+ QVERIFY(QMetaTypeId2<CustomQObject*>::Defined);
+ QVERIFY(!QMetaTypeId2<CustomQObject>::Defined);
+ QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined);
+ QVERIFY(!QMetaTypeId2<CustomNonQObject*>::Defined);
}
struct Bar
@@ -312,6 +329,7 @@ void tst_QMetaType::typeName_data()
QTest::addColumn<QString>("aTypeName");
QT_FOR_EACH_STATIC_TYPE(TYPENAME_DATA)
+ QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << static_cast<const char*>(0);
QTest::newRow("Whity<double>") << static_cast<QMetaType::Type>(::qMetaTypeId<Whity<double> >()) << QString::fromLatin1("Whity<double>");
QTest::newRow("Whity<int>") << static_cast<QMetaType::Type>(::qMetaTypeId<Whity<int> >()) << QString::fromLatin1("Whity<int>");
@@ -510,6 +528,16 @@ template<> struct TestValueFactory<QMetaType::QRegExp> {
#endif
}
};
+template<> struct TestValueFactory<QMetaType::QRegularExpression> {
+ static QRegularExpression *create()
+ {
+#ifndef QT_NO_REGEXP
+ return new QRegularExpression("abc.*def");
+#else
+ return 0;
+#endif
+ }
+};
template<> struct TestValueFactory<QMetaType::QVariant> {
static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); }
};
@@ -630,6 +658,8 @@ void tst_QMetaType::sizeOf_data()
{
QTest::addColumn<QMetaType::Type>("type");
QTest::addColumn<int>("size");
+
+ QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << 0;
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
QTest::newRow(#RealType) << QMetaType::MetaTypeName << int(QTypeInfo<RealType>::sizeOf);
FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW)
@@ -1044,6 +1074,7 @@ void tst_QMetaType::isRegistered_data()
QTest::newRow("-1") << -1 << false;
QTest::newRow("-42") << -42 << false;
QTest::newRow("IsRegisteredDummyType + 1") << (dummyTypeId + 1) << false;
+ QTest::newRow("QMetaType::UnknownType") << int(QMetaType::UnknownType) << false;
}
void tst_QMetaType::isRegistered()
diff --git a/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp b/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp
index 2d180b88ea..021079a8e7 100644
--- a/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp
@@ -90,7 +90,7 @@ static const char qt_meta_stringdata_OldNormalizeObject[] = {
};
const QMetaObject OldNormalizeObject::staticMetaObject = {
- { &QObject::staticMetaObject, qt_meta_stringdata_OldNormalizeObject,
+ { &QObject::staticMetaObject, reinterpret_cast<const QByteArrayData *>(qt_meta_stringdata_OldNormalizeObject),
qt_meta_data_OldNormalizeObject, 0 }
};
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index a6ad1d53bc..c6667ff2a8 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -1793,56 +1793,56 @@ void tst_QObject::metamethod()
QMetaMethod m;
m = mobj->method(mobj->indexOfMethod("invoke1()"));
- QVERIFY(QByteArray(m.signature()) == "invoke1()");
+ QVERIFY(m.methodSignature() == "invoke1()");
QVERIFY(m.methodType() == QMetaMethod::Method);
QVERIFY(m.access() == QMetaMethod::Public);
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("sinvoke1()"));
- QVERIFY(QByteArray(m.signature()) == "sinvoke1()");
+ QVERIFY(m.methodSignature() == "sinvoke1()");
QVERIFY(m.methodType() == QMetaMethod::Method);
QVERIFY(m.access() == QMetaMethod::Public);
QVERIFY((m.attributes() & QMetaMethod::Scriptable));
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("invoke2()"));
- QVERIFY(QByteArray(m.signature()) == "invoke2()");
+ QVERIFY(m.methodSignature() == "invoke2()");
QVERIFY(m.methodType() == QMetaMethod::Method);
QVERIFY(m.access() == QMetaMethod::Protected);
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
QVERIFY((m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("sinvoke2()"));
- QVERIFY(QByteArray(m.signature()) == "sinvoke2()");
+ QVERIFY(m.methodSignature() == "sinvoke2()");
QVERIFY(m.methodType() == QMetaMethod::Method);
QVERIFY(m.access() == QMetaMethod::Protected);
QVERIFY((m.attributes() & QMetaMethod::Scriptable));
QVERIFY((m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("invoke3()"));
- QVERIFY(QByteArray(m.signature()) == "invoke3()");
+ QVERIFY(m.methodSignature() == "invoke3()");
QVERIFY(m.methodType() == QMetaMethod::Method);
QVERIFY(m.access() == QMetaMethod::Private);
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("sinvoke3()"));
- QVERIFY(QByteArray(m.signature()) == "sinvoke3()");
+ QVERIFY(m.methodSignature() == "sinvoke3()");
QVERIFY(m.methodType() == QMetaMethod::Method);
QVERIFY(m.access() == QMetaMethod::Private);
QVERIFY((m.attributes() & QMetaMethod::Scriptable));
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("signal5()"));
- QVERIFY(QByteArray(m.signature()) == "signal5()");
+ QVERIFY(m.methodSignature() == "signal5()");
QVERIFY(m.methodType() == QMetaMethod::Signal);
QVERIFY(m.access() == QMetaMethod::Protected);
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
QVERIFY((m.attributes() & QMetaMethod::Compatibility));
m = mobj->method(mobj->indexOfMethod("aPublicSlot()"));
- QVERIFY(QByteArray(m.signature()) == "aPublicSlot()");
+ QVERIFY(m.methodSignature() == "aPublicSlot()");
QVERIFY(m.methodType() == QMetaMethod::Slot);
QVERIFY(m.access() == QMetaMethod::Public);
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
diff --git a/tests/auto/corelib/kernel/qvariant/stream/qt5.0/qregularexpression.bin b/tests/auto/corelib/kernel/qvariant/stream/qt5.0/qregularexpression.bin
new file mode 100644
index 0000000000..eaa50f7310
--- /dev/null
+++ b/tests/auto/corelib/kernel/qvariant/stream/qt5.0/qregularexpression.bin
Binary files differ
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 655c714322..05655b4df6 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -192,6 +192,7 @@ private slots:
void toLocale();
void toRegExp();
+ void toRegularExpression();
void matrix();
@@ -1319,6 +1320,21 @@ void tst_QVariant::toRegExp()
rx = variant.toRegExp();
}
+void tst_QVariant::toRegularExpression()
+{
+ QVariant variant;
+ QRegularExpression re = variant.toRegularExpression();
+ QCOMPARE(re, QRegularExpression());
+
+ variant = QRegularExpression("abc.*def");
+ re = variant.toRegularExpression();
+ QCOMPARE(re, QRegularExpression("abc.*def"));
+
+ variant = QVariant::fromValue(QRegularExpression("[ab]\\w+"));
+ re = variant.value<QRegularExpression>();
+ QCOMPARE(re, QRegularExpression("[ab]\\w+"));
+}
+
void tst_QVariant::matrix()
{
QVariant variant;
@@ -1519,6 +1535,8 @@ void tst_QVariant::writeToReadFromDataStream_data()
QTest::newRow( "qchar_null" ) << QVariant(QChar(0)) << true;
QTest::newRow( "regexp" ) << QVariant(QRegExp("foo", Qt::CaseInsensitive)) << false;
QTest::newRow( "regexp_empty" ) << QVariant(QRegExp()) << false;
+ QTest::newRow( "regularexpression" ) << QVariant(QRegularExpression("abc.*def")) << false;
+ QTest::newRow( "regularexpression_empty" ) << QVariant(QRegularExpression()) << false;
// types known to QMetaType, but not part of QVariant::Type
QTest::newRow("QMetaType::Long invalid") << QVariant(QMetaType::Long, (void *) 0) << false;
@@ -1944,6 +1962,7 @@ void tst_QVariant::typeName_data()
QTest::newRow("48") << int(QVariant::Vector3D) << QByteArray("QVector3D");
QTest::newRow("49") << int(QVariant::Vector4D) << QByteArray("QVector4D");
QTest::newRow("50") << int(QVariant::Quaternion) << QByteArray("QQuaternion");
+ QTest::newRow("51") << int(QVariant::RegularExpression) << QByteArray("QRegularExpression");
}
void tst_QVariant::typeName()
@@ -2547,9 +2566,24 @@ public:
};
Q_DECLARE_METATYPE(CustomQObjectDerived*)
+class CustomQObjectDerivedNoMetaType : public CustomQObject {
+ Q_OBJECT
+public:
+ CustomQObjectDerivedNoMetaType(QObject *parent = 0) : CustomQObject(parent) {}
+};
+
void tst_QVariant::qvariant_cast_QObject_derived()
{
{
+ CustomQObjectDerivedNoMetaType *object = new CustomQObjectDerivedNoMetaType(this);
+ QVariant data = QVariant::fromValue(object);
+ QVERIFY(data.userType() == qMetaTypeId<CustomQObjectDerivedNoMetaType*>());
+ QCOMPARE(data.value<QObject *>(), object);
+ QCOMPARE(data.value<CustomQObjectDerivedNoMetaType *>(), object);
+ QCOMPARE(data.value<CustomQObject *>(), object);
+ QVERIFY(data.value<CustomQWidget*>() == 0);
+ }
+ {
CustomQObjectDerived *object = new CustomQObjectDerived(this);
QVariant data = QVariant::fromValue(object);
@@ -3548,6 +3582,10 @@ void tst_QVariant::loadQVariantFromDataStream(QDataStream::Version version)
stream >> typeName >> loadedVariant;
const int id = QMetaType::type(typeName.toLatin1());
+ if (id == QMetaType::Void) {
+ // Void type is not supported by QVariant
+ return;
+ }
QVariant constructedVariant(static_cast<QVariant::Type>(id));
QCOMPARE(constructedVariant.userType(), id);
@@ -3567,6 +3605,10 @@ void tst_QVariant::saveQVariantFromDataStream(QDataStream::Version version)
dataFileStream >> typeName;
QByteArray data = file.readAll();
const int id = QMetaType::type(typeName.toLatin1());
+ if (id == QMetaType::Void) {
+ // Void type is not supported by QVariant
+ return;
+ }
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
@@ -3627,7 +3669,9 @@ void tst_QVariant::debugStream_data()
const char *tagName = QMetaType::typeName(id);
if (!tagName)
continue;
- QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
+ if (id != QMetaType::Void) {
+ QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
+ }
}
QTest::newRow("QBitArray(111)") << QVariant(QBitArray(3, true)) << qMetaTypeId<QBitArray>();
QTest::newRow("CustomStreamableClass") << QVariant(qMetaTypeId<CustomStreamableClass>(), 0) << qMetaTypeId<CustomStreamableClass>();
diff --git a/tests/auto/corelib/tools/qarraydata/qarraydata.pro b/tests/auto/corelib/tools/qarraydata/qarraydata.pro
new file mode 100644
index 0000000000..8e368117fa
--- /dev/null
+++ b/tests/auto/corelib/tools/qarraydata/qarraydata.pro
@@ -0,0 +1,5 @@
+TARGET = tst_qarraydata
+SOURCES += tst_qarraydata.cpp
+HEADERS += simplevector.h
+QT = core testlib
+CONFIG += testcase parallel_test
diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h
new file mode 100644
index 0000000000..fe8108bff2
--- /dev/null
+++ b/tests/auto/corelib/tools/qarraydata/simplevector.h
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QARRAY_TEST_SIMPLE_VECTOR_H
+#define QARRAY_TEST_SIMPLE_VECTOR_H
+
+#include <QtCore/qarraydata.h>
+#include <QtCore/qarraydatapointer.h>
+
+#include <algorithm>
+
+template <class T>
+struct SimpleVector
+{
+private:
+ typedef QTypedArrayData<T> Data;
+
+public:
+ typedef T value_type;
+ typedef typename Data::iterator iterator;
+ typedef typename Data::const_iterator const_iterator;
+
+ SimpleVector()
+ {
+ }
+
+ SimpleVector(size_t n, const T &t)
+ : d(Data::allocate(n))
+ {
+ if (n)
+ d->copyAppend(n, t);
+ }
+
+ SimpleVector(const T *begin, const T *end)
+ : d(Data::allocate(end - begin))
+ {
+ if (end - begin)
+ d->copyAppend(begin, end);
+ }
+
+ SimpleVector(QArrayDataPointerRef<T> ptr)
+ : d(ptr)
+ {
+ }
+
+ explicit SimpleVector(Data *ptr)
+ : d(ptr)
+ {
+ }
+
+ bool empty() const { return d->size == 0; }
+ bool isNull() const { return d.isNull(); }
+ bool isEmpty() const { return this->empty(); }
+
+ bool isStatic() const { return d->ref.isStatic(); }
+ bool isShared() const { return d->ref.isShared(); }
+ bool isSharedWith(const SimpleVector &other) const { return d == other.d; }
+ bool isSharable() const { return d->ref.isSharable(); }
+
+ void setSharable(bool sharable) { d.setSharable(sharable); }
+
+ size_t size() const { return d->size; }
+ size_t capacity() const { return d->alloc; }
+
+ iterator begin() { detach(); return d->begin(); }
+ iterator end() { detach(); return d->end(); }
+
+ const_iterator begin() const { return d->begin(); }
+ const_iterator end() const { return d->end(); }
+
+ const_iterator constBegin() const { return begin(); }
+ const_iterator constEnd() const { return end(); }
+
+ T &operator[](size_t i) { Q_ASSERT(i < size_t(d->size)); detach(); return begin()[i]; }
+ T &at(size_t i) { Q_ASSERT(i < size_t(d->size)); detach(); return begin()[i]; }
+
+ const T &operator[](size_t i) const { Q_ASSERT(i < size_t(d->size)); return begin()[i]; }
+ const T &at(size_t i) const { Q_ASSERT(i < size_t(d->size)); return begin()[i]; }
+
+ T &front()
+ {
+ Q_ASSERT(!isEmpty());
+ detach();
+ return *begin();
+ }
+
+ T &back()
+ {
+ Q_ASSERT(!isEmpty());
+ detach();
+ return *(end() - 1);
+ }
+
+ const T &front() const
+ {
+ Q_ASSERT(!isEmpty());
+ return *begin();
+ }
+
+ const T &back() const
+ {
+ Q_ASSERT(!isEmpty());
+ return *(end() - 1);
+ }
+
+ void reserve(size_t n)
+ {
+ if (n == 0)
+ return;
+
+ if (n <= capacity()) {
+ if (d->capacityReserved)
+ return;
+ if (!d->ref.isShared()) {
+ d->capacityReserved = 1;
+ return;
+ }
+ }
+
+ SimpleVector detached(Data::allocate(qMax(n, size()),
+ d->detachFlags() | Data::CapacityReserved));
+ if (size())
+ detached.d->copyAppend(constBegin(), constEnd());
+ detached.swap(*this);
+ }
+
+ void prepend(const_iterator first, const_iterator last)
+ {
+ if (!d->size) {
+ append(first, last);
+ return;
+ }
+
+ if (first == last)
+ return;
+
+ T *const begin = d->begin();
+ if (d->ref.isShared()
+ || capacity() - size() < size_t(last - first)) {
+ SimpleVector detached(Data::allocate(
+ qMax(capacity(), size() + (last - first)),
+ d->detachFlags() | Data::Grow));
+
+ detached.d->copyAppend(first, last);
+ detached.d->copyAppend(begin, begin + d->size);
+ detached.swap(*this);
+
+ return;
+ }
+
+ d->insert(begin, first, last);
+ }
+
+ void append(const_iterator first, const_iterator last)
+ {
+ if (first == last)
+ return;
+
+ if (d->ref.isShared()
+ || capacity() - size() < size_t(last - first)) {
+ SimpleVector detached(Data::allocate(
+ qMax(capacity(), size() + (last - first)),
+ d->detachFlags() | Data::Grow));
+
+ if (d->size) {
+ const T *const begin = constBegin();
+ detached.d->copyAppend(begin, begin + d->size);
+ }
+ detached.d->copyAppend(first, last);
+ detached.swap(*this);
+
+ return;
+ }
+
+ d->copyAppend(first, last);
+ }
+
+ void insert(int position, const_iterator first, const_iterator last)
+ {
+ if (position < 0)
+ position += d->size + 1;
+
+ if (position <= 0) {
+ prepend(first, last);
+ return;
+ }
+
+ if (size_t(position) >= size()) {
+ append(first, last);
+ return;
+ }
+
+ if (first == last)
+ return;
+
+ T *const begin = d->begin();
+ T *const where = begin + position;
+ const T *const end = begin + d->size;
+ if (d->ref.isShared()
+ || capacity() - size() < size_t(last - first)) {
+ SimpleVector detached(Data::allocate(
+ qMax(capacity(), size() + (last - first)),
+ d->detachFlags() | Data::Grow));
+
+ if (position)
+ detached.d->copyAppend(begin, where);
+ detached.d->copyAppend(first, last);
+ detached.d->copyAppend(where, end);
+ detached.swap(*this);
+
+ return;
+ }
+
+ if ((first >= where && first < end)
+ || (last > where && last <= end)) {
+ // Copy overlapping data first and only then shuffle it into place
+ T *start = d->begin() + position;
+ T *middle = d->end();
+
+ d->copyAppend(first, last);
+ std::rotate(start, middle, d->end());
+
+ return;
+ }
+
+ d->insert(where, first, last);
+ }
+
+ void swap(SimpleVector &other)
+ {
+ qSwap(d, other.d);
+ }
+
+ void clear()
+ {
+ d.clear();
+ }
+
+ void detach()
+ {
+ d.detach();
+ }
+
+ static SimpleVector fromRawData(const T *data, size_t size,
+ QArrayData::AllocationOptions options = Data::Default)
+ {
+ return SimpleVector(Data::fromRawData(data, size, options));
+ }
+
+private:
+ QArrayDataPointer<T> d;
+};
+
+template <class T>
+bool operator==(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
+{
+ if (lhs.isSharedWith(rhs))
+ return true;
+ if (lhs.size() != rhs.size())
+ return false;
+ return std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template <class T>
+bool operator!=(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
+{
+ return !(lhs == rhs);
+}
+
+template <class T>
+bool operator<(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
+{
+ return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
+
+template <class T>
+bool operator>(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
+{
+ return rhs < lhs;
+}
+
+template <class T>
+bool operator<=(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
+{
+ return !(rhs < lhs);
+}
+
+template <class T>
+bool operator>=(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
+{
+ return !(lhs < rhs);
+}
+
+namespace std {
+ template <class T>
+ void swap(SimpleVector<T> &v1, SimpleVector<T> &v2)
+ {
+ v1.swap(v2);
+ }
+}
+
+#endif // include guard
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
new file mode 100644
index 0000000000..9bfbac0017
--- /dev/null
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -0,0 +1,1464 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/QString>
+#include <QtCore/qarraydata.h>
+
+#include "simplevector.h"
+
+struct SharedNullVerifier
+{
+ SharedNullVerifier()
+ {
+ Q_ASSERT(QArrayData::shared_null.ref.isStatic());
+ Q_ASSERT(QArrayData::shared_null.ref.isShared());
+ Q_ASSERT(QArrayData::shared_null.ref.isSharable());
+ }
+};
+
+// This is meant to verify/ensure that shared_null is not being dynamically
+// initialized and stays away from the order-of-static-initialization fiasco.
+//
+// Of course, if this was to fail, qmake and the build should have crashed and
+// burned before we ever got to this point :-)
+SharedNullVerifier globalInit;
+
+class tst_QArrayData : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void referenceCounting();
+ void sharedNullEmpty();
+ void staticData();
+ void simpleVector();
+ void simpleVectorReserve_data();
+ void simpleVectorReserve();
+ void allocate_data();
+ void allocate();
+ void alignment_data();
+ void alignment();
+ void typedData();
+ void gccBug43247();
+ void arrayOps();
+ void setSharable_data();
+ void setSharable();
+ void fromRawData();
+ void literals();
+ void variadicLiterals();
+ void rValueReferences();
+ void grow();
+};
+
+template <class T> const T &const_(const T &t) { return t; }
+
+void tst_QArrayData::referenceCounting()
+{
+ {
+ // Reference counting initialized to 1 (owned)
+ QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(1) }, 0, 0, 0, 0 };
+
+ QCOMPARE(array.ref.atomic.load(), 1);
+
+ QVERIFY(!array.ref.isStatic());
+ QVERIFY(array.ref.isSharable());
+
+ QVERIFY(array.ref.ref());
+ QCOMPARE(array.ref.atomic.load(), 2);
+
+ QVERIFY(array.ref.deref());
+ QCOMPARE(array.ref.atomic.load(), 1);
+
+ QVERIFY(array.ref.ref());
+ QCOMPARE(array.ref.atomic.load(), 2);
+
+ QVERIFY(array.ref.deref());
+ QCOMPARE(array.ref.atomic.load(), 1);
+
+ QVERIFY(!array.ref.deref());
+ QCOMPARE(array.ref.atomic.load(), 0);
+
+ // Now would be a good time to free/release allocated data
+ }
+
+ {
+ // Reference counting initialized to 0 (non-sharable)
+ QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 };
+
+ QCOMPARE(array.ref.atomic.load(), 0);
+
+ QVERIFY(!array.ref.isStatic());
+ QVERIFY(!array.ref.isSharable());
+
+ QVERIFY(!array.ref.ref());
+ // Reference counting fails, data should be copied
+ QCOMPARE(array.ref.atomic.load(), 0);
+
+ QVERIFY(!array.ref.deref());
+ QCOMPARE(array.ref.atomic.load(), 0);
+
+ // Free/release data
+ }
+
+ {
+ // Reference counting initialized to -1 (static read-only data)
+ QArrayData array = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
+
+ QCOMPARE(array.ref.atomic.load(), -1);
+
+ QVERIFY(array.ref.isStatic());
+ QVERIFY(array.ref.isSharable());
+
+ QVERIFY(array.ref.ref());
+ QCOMPARE(array.ref.atomic.load(), -1);
+
+ QVERIFY(array.ref.deref());
+ QCOMPARE(array.ref.atomic.load(), -1);
+ }
+}
+
+void tst_QArrayData::sharedNullEmpty()
+{
+ QArrayData *null = const_cast<QArrayData *>(&QArrayData::shared_null);
+ QArrayData *empty = QArrayData::allocate(1, Q_ALIGNOF(QArrayData), 0);
+
+ QVERIFY(null->ref.isStatic());
+ QVERIFY(null->ref.isSharable());
+ QVERIFY(null->ref.isShared());
+
+ QVERIFY(empty->ref.isStatic());
+ QVERIFY(empty->ref.isSharable());
+ QVERIFY(empty->ref.isShared());
+
+ QCOMPARE(null->ref.atomic.load(), -1);
+ QCOMPARE(empty->ref.atomic.load(), -1);
+
+ QVERIFY(null->ref.ref());
+ QVERIFY(empty->ref.ref());
+
+ QCOMPARE(null->ref.atomic.load(), -1);
+ QCOMPARE(empty->ref.atomic.load(), -1);
+
+ QVERIFY(null->ref.deref());
+ QVERIFY(empty->ref.deref());
+
+ QCOMPARE(null->ref.atomic.load(), -1);
+ QCOMPARE(empty->ref.atomic.load(), -1);
+
+ QVERIFY(null != empty);
+
+ QCOMPARE(null->size, 0);
+ QCOMPARE(null->alloc, 0u);
+ QCOMPARE(null->capacityReserved, 0u);
+
+ QCOMPARE(empty->size, 0);
+ QCOMPARE(empty->alloc, 0u);
+ QCOMPARE(empty->capacityReserved, 0u);
+}
+
+void tst_QArrayData::staticData()
+{
+ QStaticArrayData<char, 10> charArray = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(char, 10),
+ { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }
+ };
+ QStaticArrayData<int, 10> intArray = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 10),
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+ };
+ QStaticArrayData<double, 10> doubleArray = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(double, 10),
+ { 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f }
+ };
+
+ QCOMPARE(charArray.header.size, 10);
+ QCOMPARE(intArray.header.size, 10);
+ QCOMPARE(doubleArray.header.size, 10);
+
+ QCOMPARE(charArray.header.data(), reinterpret_cast<void *>(&charArray.data));
+ QCOMPARE(intArray.header.data(), reinterpret_cast<void *>(&intArray.data));
+ QCOMPARE(doubleArray.header.data(), reinterpret_cast<void *>(&doubleArray.data));
+}
+
+void tst_QArrayData::simpleVector()
+{
+ QArrayData data0 = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
+ QStaticArrayData<int, 7> data1 = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 7),
+ { 0, 1, 2, 3, 4, 5, 6 }
+ };
+
+ int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ SimpleVector<int> v1;
+ SimpleVector<int> v2(v1);
+ SimpleVector<int> v3(static_cast<QTypedArrayData<int> *>(&data0));
+ SimpleVector<int> v4(static_cast<QTypedArrayData<int> *>(&data1.header));
+ SimpleVector<int> v5(static_cast<QTypedArrayData<int> *>(&data0));
+ SimpleVector<int> v6(static_cast<QTypedArrayData<int> *>(&data1.header));
+ SimpleVector<int> v7(10, 5);
+ SimpleVector<int> v8(array, array + sizeof(array)/sizeof(*array));
+
+ v3 = v1;
+ v1.swap(v3);
+ v4.clear();
+
+ QVERIFY(v1.isNull());
+ QVERIFY(v2.isNull());
+ QVERIFY(v3.isNull());
+ QVERIFY(v4.isNull());
+ QVERIFY(!v5.isNull());
+ QVERIFY(!v6.isNull());
+ QVERIFY(!v7.isNull());
+ QVERIFY(!v8.isNull());
+
+ QVERIFY(v1.isEmpty());
+ QVERIFY(v2.isEmpty());
+ QVERIFY(v3.isEmpty());
+ QVERIFY(v4.isEmpty());
+ QVERIFY(v5.isEmpty());
+ QVERIFY(!v6.isEmpty());
+ QVERIFY(!v7.isEmpty());
+ QVERIFY(!v8.isEmpty());
+
+ QCOMPARE(v1.size(), size_t(0));
+ QCOMPARE(v2.size(), size_t(0));
+ QCOMPARE(v3.size(), size_t(0));
+ QCOMPARE(v4.size(), size_t(0));
+ QCOMPARE(v5.size(), size_t(0));
+ QCOMPARE(v6.size(), size_t(7));
+ QCOMPARE(v7.size(), size_t(10));
+ QCOMPARE(v8.size(), size_t(10));
+
+ QCOMPARE(v1.capacity(), size_t(0));
+ QCOMPARE(v2.capacity(), size_t(0));
+ QCOMPARE(v3.capacity(), size_t(0));
+ QCOMPARE(v4.capacity(), size_t(0));
+ QCOMPARE(v5.capacity(), size_t(0));
+ // v6.capacity() is unspecified, for now
+ QVERIFY(v7.capacity() >= size_t(10));
+ QVERIFY(v8.capacity() >= size_t(10));
+
+ QVERIFY(v1.isStatic());
+ QVERIFY(v2.isStatic());
+ QVERIFY(v3.isStatic());
+ QVERIFY(v4.isStatic());
+ QVERIFY(v5.isStatic());
+ QVERIFY(v6.isStatic());
+ QVERIFY(!v7.isStatic());
+ QVERIFY(!v8.isStatic());
+
+ QVERIFY(v1.isShared());
+ QVERIFY(v2.isShared());
+ QVERIFY(v3.isShared());
+ QVERIFY(v4.isShared());
+ QVERIFY(v5.isShared());
+ QVERIFY(v6.isShared());
+ QVERIFY(!v7.isShared());
+ QVERIFY((SimpleVector<int>(v7), v7.isShared()));
+ QVERIFY(!v7.isShared());
+ QVERIFY(!v8.isShared());
+
+ QVERIFY(v1.isSharable());
+ QVERIFY(v2.isSharable());
+ QVERIFY(v3.isSharable());
+ QVERIFY(v4.isSharable());
+ QVERIFY(v5.isSharable());
+ QVERIFY(v6.isSharable());
+ QVERIFY(v7.isSharable());
+ QVERIFY(v8.isSharable());
+
+ QVERIFY(v1.isSharedWith(v2));
+ QVERIFY(v1.isSharedWith(v3));
+ QVERIFY(v1.isSharedWith(v4));
+ QVERIFY(!v1.isSharedWith(v5));
+ QVERIFY(!v1.isSharedWith(v6));
+
+ QCOMPARE((void *)v1.constBegin(), (void *)v1.constEnd());
+ QCOMPARE((void *)v4.constBegin(), (void *)v4.constEnd());
+ QCOMPARE((void *)(v6.constBegin() + v6.size()), (void *)v6.constEnd());
+ QCOMPARE((void *)(v7.constBegin() + v7.size()), (void *)v7.constEnd());
+ QCOMPARE((void *)(v8.constBegin() + v8.size()), (void *)v8.constEnd());
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 == v3);
+ QVERIFY(v1 == v4);
+ QVERIFY(v1 == v5);
+ QVERIFY(!(v1 == v6));
+
+ QVERIFY(v1 != v6);
+ QVERIFY(v4 != v6);
+ QVERIFY(v5 != v6);
+ QVERIFY(!(v1 != v5));
+
+ QVERIFY(v1 < v6);
+ QVERIFY(!(v6 < v1));
+ QVERIFY(v6 > v1);
+ QVERIFY(!(v1 > v6));
+ QVERIFY(v1 <= v6);
+ QVERIFY(!(v6 <= v1));
+ QVERIFY(v6 >= v1);
+ QVERIFY(!(v1 >= v6));
+
+ {
+ SimpleVector<int> temp(v6);
+
+ QCOMPARE(const_(v6).front(), 0);
+ QCOMPARE(const_(v6).back(), 6);
+
+ QVERIFY(temp.isShared());
+ QVERIFY(temp.isSharedWith(v6));
+
+ QCOMPARE(temp.front(), 0);
+ QCOMPARE(temp.back(), 6);
+
+ // Detached
+ QVERIFY(!temp.isShared());
+ const int *const tempBegin = temp.begin();
+
+ for (size_t i = 0; i < v6.size(); ++i) {
+ QCOMPARE(const_(v6)[i], int(i));
+ QCOMPARE(const_(v6).at(i), int(i));
+ QCOMPARE(&const_(v6)[i], &const_(v6).at(i));
+
+ QCOMPARE(const_(v8)[i], const_(v6)[i]);
+
+ QCOMPARE(temp[i], int(i));
+ QCOMPARE(temp.at(i), int(i));
+ QCOMPARE(&temp[i], &temp.at(i));
+ }
+
+ // A single detach should do
+ QCOMPARE(temp.begin(), tempBegin);
+ }
+
+ {
+ int count = 0;
+ Q_FOREACH (int value, v7) {
+ QCOMPARE(value, 5);
+ ++count;
+ }
+
+ QCOMPARE(count, 10);
+ }
+
+ {
+ int count = 0;
+ Q_FOREACH (int value, v8) {
+ QCOMPARE(value, count);
+ ++count;
+ }
+
+ QCOMPARE(count, 10);
+ }
+
+ v5 = v6;
+ QVERIFY(v5.isSharedWith(v6));
+ QVERIFY(!v1.isSharedWith(v5));
+
+ v1.swap(v6);
+ QVERIFY(v6.isNull());
+ QVERIFY(v1.isSharedWith(v5));
+
+ {
+ using std::swap;
+ swap(v1, v6);
+ QVERIFY(v5.isSharedWith(v6));
+ QVERIFY(!v1.isSharedWith(v5));
+ }
+
+ v1.prepend(array, array + sizeof(array)/sizeof(array[0]));
+ QCOMPARE(v1.size(), size_t(10));
+ QVERIFY(v1 == v8);
+
+ v6 = v1;
+ QVERIFY(v1.isSharedWith(v6));
+
+ v1.prepend(array, array + sizeof(array)/sizeof(array[0]));
+ QVERIFY(!v1.isSharedWith(v6));
+ QCOMPARE(v1.size(), size_t(20));
+ QCOMPARE(v6.size(), size_t(10));
+
+ for (int i = 0; i < 20; ++i)
+ QCOMPARE(v1[i], v6[i % 10]);
+
+ v1.clear();
+
+ v1.append(array, array + sizeof(array)/sizeof(array[0]));
+ QCOMPARE(v1.size(), size_t(10));
+ QVERIFY(v1 == v8);
+
+ v6 = v1;
+ QVERIFY(v1.isSharedWith(v6));
+
+ v1.append(array, array + sizeof(array)/sizeof(array[0]));
+ QVERIFY(!v1.isSharedWith(v6));
+ QCOMPARE(v1.size(), size_t(20));
+ QCOMPARE(v6.size(), size_t(10));
+
+ for (int i = 0; i < 20; ++i)
+ QCOMPARE(v1[i], v6[i % 10]);
+
+ v1.insert(0, v6.constBegin(), v6.constEnd());
+ QCOMPARE(v1.size(), size_t(30));
+
+ v6 = v1;
+ QVERIFY(v1.isSharedWith(v6));
+
+ v1.insert(10, v6.constBegin(), v6.constEnd());
+ QVERIFY(!v1.isSharedWith(v6));
+ QCOMPARE(v1.size(), size_t(60));
+ QCOMPARE(v6.size(), size_t(30));
+
+ for (int i = 0; i < 30; ++i)
+ QCOMPARE(v6[i], v8[i % 10]);
+
+ v1.insert(v1.size(), v6.constBegin(), v6.constEnd());
+ QCOMPARE(v1.size(), size_t(90));
+
+ v1.insert(-1, v8.constBegin(), v8.constEnd());
+ QCOMPARE(v1.size(), size_t(100));
+
+ v1.insert(-11, v8.constBegin(), v8.constEnd());
+ QCOMPARE(v1.size(), size_t(110));
+
+ v1.insert(-200, v8.constBegin(), v8.constEnd());
+ QCOMPARE(v1.size(), size_t(120));
+
+ for (int i = 0; i < 120; ++i)
+ QCOMPARE(v1[i], v8[i % 10]);
+
+ {
+ v7.setSharable(true);
+ QVERIFY(v7.isSharable());
+
+ SimpleVector<int> copy1(v7);
+ QVERIFY(copy1.isSharedWith(v7));
+
+ v7.setSharable(false);
+ QVERIFY(!v7.isSharable());
+
+ QVERIFY(!copy1.isSharedWith(v7));
+ QCOMPARE(v7.size(), copy1.size());
+ for (size_t i = 0; i < copy1.size(); ++i)
+ QCOMPARE(v7[i], copy1[i]);
+
+ SimpleVector<int> clone(v7);
+ QVERIFY(!clone.isSharedWith(v7));
+ QCOMPARE(clone.size(), copy1.size());
+ for (size_t i = 0; i < copy1.size(); ++i)
+ QCOMPARE(clone[i], copy1[i]);
+
+ v7.setSharable(true);
+ QVERIFY(v7.isSharable());
+
+ SimpleVector<int> copy2(v7);
+ QVERIFY(copy2.isSharedWith(v7));
+ }
+
+ {
+ SimpleVector<int> null;
+ SimpleVector<int> empty(0, 5);
+
+ QVERIFY(null.isSharable());
+ QVERIFY(empty.isSharable());
+
+ null.setSharable(true);
+ empty.setSharable(true);
+
+ QVERIFY(null.isSharable());
+ QVERIFY(empty.isSharable());
+
+ QVERIFY(null.isEmpty());
+ QVERIFY(empty.isEmpty());
+
+ null.setSharable(false);
+ empty.setSharable(false);
+
+ QVERIFY(!null.isSharable());
+ QVERIFY(!empty.isSharable());
+
+ QVERIFY(null.isEmpty());
+ QVERIFY(empty.isEmpty());
+
+ null.setSharable(true);
+ empty.setSharable(true);
+
+ QVERIFY(null.isSharable());
+ QVERIFY(empty.isSharable());
+
+ QVERIFY(null.isEmpty());
+ QVERIFY(empty.isEmpty());
+ }
+}
+
+Q_DECLARE_METATYPE(SimpleVector<int>)
+
+void tst_QArrayData::simpleVectorReserve_data()
+{
+ QTest::addColumn<SimpleVector<int> >("vector");
+ QTest::addColumn<size_t>("capacity");
+ QTest::addColumn<size_t>("size");
+
+ QTest::newRow("null") << SimpleVector<int>() << size_t(0) << size_t(0);
+ QTest::newRow("empty") << SimpleVector<int>(0, 42) << size_t(0) << size_t(0);
+ QTest::newRow("non-empty") << SimpleVector<int>(5, 42) << size_t(5) << size_t(5);
+
+ static const QStaticArrayData<int, 15> array = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 15),
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } };
+ QArrayDataPointerRef<int> p = {
+ static_cast<QTypedArrayData<int> *>(
+ const_cast<QArrayData *>(&array.header)) };
+
+ QTest::newRow("static") << SimpleVector<int>(p) << size_t(0) << size_t(15);
+ QTest::newRow("raw-data") << SimpleVector<int>::fromRawData(array.data, 15) << size_t(0) << size_t(15);
+}
+
+void tst_QArrayData::simpleVectorReserve()
+{
+ QFETCH(SimpleVector<int>, vector);
+ QFETCH(size_t, capacity);
+ QFETCH(size_t, size);
+
+ QVERIFY(!capacity || capacity >= size);
+
+ QCOMPARE(vector.capacity(), capacity);
+ QCOMPARE(vector.size(), size);
+
+ const SimpleVector<int> copy(vector);
+
+ vector.reserve(0);
+ QCOMPARE(vector.capacity(), capacity);
+ QCOMPARE(vector.size(), size);
+
+ vector.reserve(10);
+
+ // zero-capacity (immutable) resets with detach
+ if (!capacity)
+ capacity = size;
+
+ QCOMPARE(vector.capacity(), qMax(size_t(10), capacity));
+ QCOMPARE(vector.size(), size);
+
+ vector.reserve(20);
+ QCOMPARE(vector.capacity(), size_t(20));
+ QCOMPARE(vector.size(), size);
+
+ vector.reserve(30);
+ QCOMPARE(vector.capacity(), size_t(30));
+ QCOMPARE(vector.size(), size);
+
+ QVERIFY(vector == copy);
+}
+
+struct Deallocator
+{
+ Deallocator(size_t objectSize, size_t alignment)
+ : objectSize(objectSize)
+ , alignment(alignment)
+ {
+ }
+
+ ~Deallocator()
+ {
+ Q_FOREACH (QArrayData *data, headers)
+ QArrayData::deallocate(data, objectSize, alignment);
+ }
+
+ size_t objectSize;
+ size_t alignment;
+ QVector<QArrayData *> headers;
+};
+
+Q_DECLARE_METATYPE(const QArrayData *)
+Q_DECLARE_METATYPE(QArrayData::AllocationOptions)
+
+void tst_QArrayData::allocate_data()
+{
+ QTest::addColumn<size_t>("objectSize");
+ QTest::addColumn<size_t>("alignment");
+ QTest::addColumn<QArrayData::AllocationOptions>("allocateOptions");
+ QTest::addColumn<bool>("isCapacityReserved");
+ QTest::addColumn<bool>("isSharable");
+ QTest::addColumn<const QArrayData *>("commonEmpty");
+
+ struct {
+ char const *typeName;
+ size_t objectSize;
+ size_t alignment;
+ } types[] = {
+ { "char", sizeof(char), Q_ALIGNOF(char) },
+ { "short", sizeof(short), Q_ALIGNOF(short) },
+ { "void *", sizeof(void *), Q_ALIGNOF(void *) }
+ };
+
+ QArrayData *shared_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0);
+ QArrayData *unsharable_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0, QArrayData::Unsharable);
+
+ QVERIFY(shared_empty);
+ QVERIFY(unsharable_empty);
+
+ struct {
+ char const *description;
+ QArrayData::AllocationOptions allocateOptions;
+ bool isCapacityReserved;
+ bool isSharable;
+ const QArrayData *commonEmpty;
+ } options[] = {
+ { "Default", QArrayData::Default, false, true, shared_empty },
+ { "Reserved", QArrayData::CapacityReserved, true, true, shared_empty },
+ { "Reserved | Unsharable",
+ QArrayData::CapacityReserved | QArrayData::Unsharable, true, false,
+ unsharable_empty },
+ { "Unsharable", QArrayData::Unsharable, false, false, unsharable_empty },
+ { "Grow", QArrayData::Grow, false, true, shared_empty }
+ };
+
+ for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i)
+ for (size_t j = 0; j < sizeof(options)/sizeof(options[0]); ++j)
+ QTest::newRow(qPrintable(
+ QLatin1String(types[i].typeName)
+ + QLatin1String(": ")
+ + QLatin1String(options[j].description)))
+ << types[i].objectSize << types[i].alignment
+ << options[j].allocateOptions << options[j].isCapacityReserved
+ << options[j].isSharable << options[j].commonEmpty;
+}
+
+void tst_QArrayData::allocate()
+{
+ QFETCH(size_t, objectSize);
+ QFETCH(size_t, alignment);
+ QFETCH(QArrayData::AllocationOptions, allocateOptions);
+ QFETCH(bool, isCapacityReserved);
+ QFETCH(bool, isSharable);
+ QFETCH(const QArrayData *, commonEmpty);
+
+ // Minimum alignment that can be requested is that of QArrayData.
+ // Typically, this alignment is sizeof(void *) and ensured by malloc.
+ size_t minAlignment = qMax(alignment, Q_ALIGNOF(QArrayData));
+
+ // Shared Empty
+ QCOMPARE(QArrayData::allocate(objectSize, minAlignment, 0,
+ QArrayData::AllocationOptions(allocateOptions)), commonEmpty);
+
+ Deallocator keeper(objectSize, minAlignment);
+ keeper.headers.reserve(1024);
+
+ for (int capacity = 1; capacity <= 1024; capacity <<= 1) {
+ QArrayData *data = QArrayData::allocate(objectSize, minAlignment,
+ capacity, QArrayData::AllocationOptions(allocateOptions));
+ keeper.headers.append(data);
+
+ QCOMPARE(data->size, 0);
+ if (allocateOptions & QArrayData::Grow)
+ QVERIFY(data->alloc > uint(capacity));
+ else
+ QCOMPARE(data->alloc, uint(capacity));
+ QCOMPARE(data->capacityReserved, uint(isCapacityReserved));
+ QCOMPARE(data->ref.isSharable(), isSharable);
+
+ // Check that the allocated array can be used. Best tested with a
+ // memory checker, such as valgrind, running.
+ ::memset(data->data(), 'A', objectSize * capacity);
+ }
+}
+
+class Unaligned
+{
+ char dummy[8];
+};
+
+void tst_QArrayData::alignment_data()
+{
+ QTest::addColumn<size_t>("alignment");
+
+ for (int i = 1; i < 10; ++i) {
+ size_t alignment = 1u << i;
+ QTest::newRow(qPrintable(QString::number(alignment))) << alignment;
+ }
+}
+
+void tst_QArrayData::alignment()
+{
+ QFETCH(size_t, alignment);
+
+ // Minimum alignment that can be requested is that of QArrayData.
+ // Typically, this alignment is sizeof(void *) and ensured by malloc.
+ size_t minAlignment = qMax(alignment, Q_ALIGNOF(QArrayData));
+
+ Deallocator keeper(sizeof(Unaligned), minAlignment);
+ keeper.headers.reserve(100);
+
+ for (int i = 0; i < 100; ++i) {
+ QArrayData *data = QArrayData::allocate(sizeof(Unaligned),
+ minAlignment, 8, QArrayData::Default);
+ keeper.headers.append(data);
+
+ QVERIFY(data);
+ QCOMPARE(data->size, 0);
+ QVERIFY(data->alloc >= uint(8));
+
+ // These conditions should hold as long as header and array are
+ // allocated together
+ QVERIFY(data->offset >= qptrdiff(sizeof(QArrayData)));
+ QVERIFY(data->offset <= qptrdiff(sizeof(QArrayData)
+ + minAlignment - Q_ALIGNOF(QArrayData)));
+
+ // Data is aligned
+ QCOMPARE(quintptr(data->data()) % alignment, quintptr(0u));
+
+ // Check that the allocated array can be used. Best tested with a
+ // memory checker, such as valgrind, running.
+ ::memset(data->data(), 'A', sizeof(Unaligned) * 8);
+ }
+}
+
+void tst_QArrayData::typedData()
+{
+ QStaticArrayData<int, 10> data = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 10),
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+ };
+ QCOMPARE(data.header.size, 10);
+
+ {
+ QTypedArrayData<int> *array =
+ static_cast<QTypedArrayData<int> *>(&data.header);
+ QCOMPARE(array->data(), data.data);
+
+ int j = 0;
+ for (QTypedArrayData<int>::iterator iter = array->begin();
+ iter != array->end(); ++iter, ++j)
+ QCOMPARE(iter, data.data + j);
+ QCOMPARE(j, 10);
+ }
+
+ {
+ const QTypedArrayData<int> *array =
+ static_cast<const QTypedArrayData<int> *>(&data.header);
+
+ QCOMPARE(array->data(), data.data);
+
+ int j = 0;
+ for (QTypedArrayData<int>::const_iterator iter = array->begin();
+ iter != array->end(); ++iter, ++j)
+ QCOMPARE(iter, data.data + j);
+ QCOMPARE(j, 10);
+ }
+
+ {
+ QTypedArrayData<int> *null = QTypedArrayData<int>::sharedNull();
+ QTypedArrayData<int> *empty = QTypedArrayData<int>::allocate(0);
+
+ QVERIFY(null != empty);
+
+ QCOMPARE(null->size, 0);
+ QCOMPARE(empty->size, 0);
+
+ QCOMPARE(null->begin(), null->end());
+ QCOMPARE(empty->begin(), empty->end());
+ }
+
+
+ {
+ Deallocator keeper(sizeof(char),
+ Q_ALIGNOF(QTypedArrayData<char>::AlignmentDummy));
+ QArrayData *array = QTypedArrayData<char>::allocate(10);
+ keeper.headers.append(array);
+
+ QVERIFY(array);
+ QCOMPARE(array->size, 0);
+ QCOMPARE(array->alloc, 10u);
+
+ // Check that the allocated array can be used. Best tested with a
+ // memory checker, such as valgrind, running.
+ ::memset(array->data(), 0, 10 * sizeof(char));
+
+ keeper.headers.clear();
+ QTypedArrayData<short>::deallocate(array);
+
+ QVERIFY(true);
+ }
+
+ {
+ Deallocator keeper(sizeof(short),
+ Q_ALIGNOF(QTypedArrayData<short>::AlignmentDummy));
+ QArrayData *array = QTypedArrayData<short>::allocate(10);
+ keeper.headers.append(array);
+
+ QVERIFY(array);
+ QCOMPARE(array->size, 0);
+ QCOMPARE(array->alloc, 10u);
+
+ // Check that the allocated array can be used. Best tested with a
+ // memory checker, such as valgrind, running.
+ ::memset(array->data(), 0, 10 * sizeof(short));
+
+ keeper.headers.clear();
+ QTypedArrayData<short>::deallocate(array);
+
+ QVERIFY(true);
+ }
+
+ {
+ Deallocator keeper(sizeof(double),
+ Q_ALIGNOF(QTypedArrayData<double>::AlignmentDummy));
+ QArrayData *array = QTypedArrayData<double>::allocate(10);
+ keeper.headers.append(array);
+
+ QVERIFY(array);
+ QCOMPARE(array->size, 0);
+ QCOMPARE(array->alloc, 10u);
+
+ // Check that the allocated array can be used. Best tested with a
+ // memory checker, such as valgrind, running.
+ ::memset(array->data(), 0, 10 * sizeof(double));
+
+ keeper.headers.clear();
+ QTypedArrayData<double>::deallocate(array);
+
+ QVERIFY(true);
+ }
+}
+
+void tst_QArrayData::gccBug43247()
+{
+ // This test tries to verify QArrayData is not affected by GCC optimizer
+ // bug #43247.
+ // Reported on GCC 4.4.3, Linux, affects QVector
+
+ QTest::ignoreMessage(QtDebugMsg, "GCC Optimization bug #43247 not triggered (3)");
+ QTest::ignoreMessage(QtDebugMsg, "GCC Optimization bug #43247 not triggered (4)");
+ QTest::ignoreMessage(QtDebugMsg, "GCC Optimization bug #43247 not triggered (5)");
+ QTest::ignoreMessage(QtDebugMsg, "GCC Optimization bug #43247 not triggered (6)");
+ QTest::ignoreMessage(QtDebugMsg, "GCC Optimization bug #43247 not triggered (7)");
+
+ SimpleVector<int> array(10, 0);
+ // QVector<int> vector(10, 0);
+
+ for (int i = 0; i < 10; ++i) {
+ if (i >= 3 && i < 8)
+ qDebug("GCC Optimization bug #43247 not triggered (%i)", i);
+
+ // When access to data is implemented through an array of size 1, this
+ // line lets the compiler assume i == 0, and the conditional above is
+ // skipped.
+ QVERIFY(array.at(i) == 0);
+ // QVERIFY(vector.at(i) == 0);
+ }
+}
+
+struct CountedObject
+{
+ CountedObject()
+ : id(liveCount++)
+ {
+ }
+
+ CountedObject(const CountedObject &other)
+ : id(other.id)
+ {
+ ++liveCount;
+ }
+
+ ~CountedObject()
+ {
+ --liveCount;
+ }
+
+ CountedObject &operator=(const CountedObject &other)
+ {
+ id = other.id;
+ return *this;
+ }
+
+ struct LeakChecker
+ {
+ LeakChecker()
+ : previousLiveCount(liveCount)
+ {
+ }
+
+ ~LeakChecker()
+ {
+ QCOMPARE(liveCount, previousLiveCount);
+ }
+
+ private:
+ const size_t previousLiveCount;
+ };
+
+ size_t id; // not unique
+ static size_t liveCount;
+};
+
+size_t CountedObject::liveCount = 0;
+
+void tst_QArrayData::arrayOps()
+{
+ CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker)
+
+ const int intArray[5] = { 80, 101, 100, 114, 111 };
+ const QString stringArray[5] = {
+ QLatin1String("just"),
+ QLatin1String("for"),
+ QLatin1String("testing"),
+ QLatin1String("a"),
+ QLatin1String("vector")
+ };
+ const CountedObject objArray[5];
+
+ QVERIFY(!QTypeInfo<int>::isComplex && !QTypeInfo<int>::isStatic);
+ QVERIFY(QTypeInfo<QString>::isComplex && !QTypeInfo<QString>::isStatic);
+ QVERIFY(QTypeInfo<CountedObject>::isComplex && QTypeInfo<CountedObject>::isStatic);
+
+ QCOMPARE(CountedObject::liveCount, size_t(5));
+ for (size_t i = 0; i < 5; ++i)
+ QCOMPARE(objArray[i].id, i);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // copyAppend (I)
+ SimpleVector<int> vi(intArray, intArray + 5);
+ SimpleVector<QString> vs(stringArray, stringArray + 5);
+ SimpleVector<CountedObject> vo(objArray, objArray + 5);
+
+ QCOMPARE(CountedObject::liveCount, size_t(10));
+ for (int i = 0; i < 5; ++i) {
+ QCOMPARE(vi[i], intArray[i]);
+ QVERIFY(vs[i].isSharedWith(stringArray[i]));
+ QCOMPARE(vo[i].id, objArray[i].id);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // destroyAll
+ vi.clear();
+ vs.clear();
+ vo.clear();
+
+ QCOMPARE(CountedObject::liveCount, size_t(5));
+
+ ////////////////////////////////////////////////////////////////////////////
+ // copyAppend (II)
+ int referenceInt = 7;
+ QString referenceString = QLatin1String("reference");
+ CountedObject referenceObject;
+
+ vi = SimpleVector<int>(5, referenceInt);
+ vs = SimpleVector<QString>(5, referenceString);
+ vo = SimpleVector<CountedObject>(5, referenceObject);
+
+ QCOMPARE(vi.size(), size_t(5));
+ QCOMPARE(vs.size(), size_t(5));
+ QCOMPARE(vo.size(), size_t(5));
+
+ QCOMPARE(CountedObject::liveCount, size_t(11));
+ for (int i = 0; i < 5; ++i) {
+ QCOMPARE(vi[i], referenceInt);
+ QVERIFY(vs[i].isSharedWith(referenceString));
+ QCOMPARE(vo[i].id, referenceObject.id);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // insert
+ vi.reserve(30);
+ vs.reserve(30);
+ vo.reserve(30);
+
+ QCOMPARE(vi.size(), size_t(5));
+ QCOMPARE(vs.size(), size_t(5));
+ QCOMPARE(vo.size(), size_t(5));
+
+ QVERIFY(vi.capacity() >= 30);
+ QVERIFY(vs.capacity() >= 30);
+ QVERIFY(vo.capacity() >= 30);
+
+ // Displace as many elements as array is extended by
+ vi.insert(0, intArray, intArray + 5);
+ vs.insert(0, stringArray, stringArray + 5);
+ vo.insert(0, objArray, objArray + 5);
+
+ QCOMPARE(vi.size(), size_t(10));
+ QCOMPARE(vs.size(), size_t(10));
+ QCOMPARE(vo.size(), size_t(10));
+
+ // Displace more elements than array is extended by
+ vi.insert(0, intArray, intArray + 5);
+ vs.insert(0, stringArray, stringArray + 5);
+ vo.insert(0, objArray, objArray + 5);
+
+ QCOMPARE(vi.size(), size_t(15));
+ QCOMPARE(vs.size(), size_t(15));
+ QCOMPARE(vo.size(), size_t(15));
+
+ // Displace less elements than array is extended by
+ vi.insert(5, vi.constBegin(), vi.constEnd());
+ vs.insert(5, vs.constBegin(), vs.constEnd());
+ vo.insert(5, vo.constBegin(), vo.constEnd());
+
+ QCOMPARE(vi.size(), size_t(30));
+ QCOMPARE(vs.size(), size_t(30));
+ QCOMPARE(vo.size(), size_t(30));
+
+ QCOMPARE(CountedObject::liveCount, size_t(36));
+ for (int i = 0; i < 15; ++i) {
+ QCOMPARE(vi[i], intArray[i % 5]);
+ QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
+ QCOMPARE(vo[i].id, objArray[i % 5].id);
+ }
+
+ for (int i = 15; i < 20; ++i) {
+ QCOMPARE(vi[i], referenceInt);
+ QVERIFY(vs[i].isSharedWith(referenceString));
+ QCOMPARE(vo[i].id, referenceObject.id);
+ }
+
+ for (int i = 20; i < 25; ++i) {
+ QCOMPARE(vi[i], intArray[i % 5]);
+ QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
+ QCOMPARE(vo[i].id, objArray[i % 5].id);
+ }
+
+ for (int i = 25; i < 30; ++i) {
+ QCOMPARE(vi[i], referenceInt);
+ QVERIFY(vs[i].isSharedWith(referenceString));
+ QCOMPARE(vo[i].id, referenceObject.id);
+ }
+}
+
+Q_DECLARE_METATYPE(QArrayDataPointer<int>)
+
+static inline bool arrayIsFilledWith(const QArrayDataPointer<int> &array,
+ int fillValue, size_t size)
+{
+ const int *iter = array->begin();
+ const int *const end = array->end();
+
+ for (size_t i = 0; i < size; ++i, ++iter)
+ if (*iter != fillValue)
+ return false;
+
+ if (iter != end)
+ return false;
+
+ return true;
+}
+
+void tst_QArrayData::setSharable_data()
+{
+ QTest::addColumn<QArrayDataPointer<int> >("array");
+ QTest::addColumn<size_t>("size");
+ QTest::addColumn<size_t>("capacity");
+ QTest::addColumn<bool>("isCapacityReserved");
+ QTest::addColumn<int>("fillValue");
+
+ QArrayDataPointer<int> null;
+ QArrayDataPointer<int> empty; empty.clear();
+
+ static QStaticArrayData<int, 10> staticArrayData = {
+ Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 10),
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }
+ };
+
+ QArrayDataPointer<int> emptyReserved(QTypedArrayData<int>::allocate(5,
+ QArrayData::CapacityReserved));
+ QArrayDataPointer<int> nonEmpty(QTypedArrayData<int>::allocate(10,
+ QArrayData::Default));
+ QArrayDataPointer<int> nonEmptyReserved(QTypedArrayData<int>::allocate(15,
+ QArrayData::CapacityReserved));
+ QArrayDataPointer<int> staticArray(
+ static_cast<QTypedArrayData<int> *>(&staticArrayData.header));
+ QArrayDataPointer<int> rawData(
+ QTypedArrayData<int>::fromRawData(staticArrayData.data, 10));
+
+ nonEmpty->copyAppend(5, 1);
+ nonEmptyReserved->copyAppend(7, 2);
+
+ QTest::newRow("shared-null") << null << size_t(0) << size_t(0) << false << 0;
+ QTest::newRow("shared-empty") << empty << size_t(0) << size_t(0) << false << 0;
+ // unsharable-empty implicitly tested in shared-empty
+ QTest::newRow("empty-reserved") << emptyReserved << size_t(0) << size_t(5) << true << 0;
+ QTest::newRow("non-empty") << nonEmpty << size_t(5) << size_t(10) << false << 1;
+ QTest::newRow("non-empty-reserved") << nonEmptyReserved << size_t(7) << size_t(15) << true << 2;
+ QTest::newRow("static-array") << staticArray << size_t(10) << size_t(0) << false << 3;
+ QTest::newRow("raw-data") << rawData << size_t(10) << size_t(0) << false << 3;
+}
+
+void tst_QArrayData::setSharable()
+{
+ QFETCH(QArrayDataPointer<int>, array);
+ QFETCH(size_t, size);
+ QFETCH(size_t, capacity);
+ QFETCH(bool, isCapacityReserved);
+ QFETCH(int, fillValue);
+
+ QVERIFY(array->ref.isShared()); // QTest has a copy
+ QVERIFY(array->ref.isSharable());
+
+ QCOMPARE(size_t(array->size), size);
+ QCOMPARE(size_t(array->alloc), capacity);
+ QCOMPARE(bool(array->capacityReserved), isCapacityReserved);
+ QVERIFY(arrayIsFilledWith(array, fillValue, size));
+
+ // shared-null becomes shared-empty, may otherwise detach
+ array.setSharable(true);
+
+ QVERIFY(array->ref.isSharable());
+ QVERIFY(arrayIsFilledWith(array, fillValue, size));
+
+ {
+ QArrayDataPointer<int> copy(array);
+ QVERIFY(array->ref.isShared());
+ QVERIFY(array->ref.isSharable());
+ QCOMPARE(copy.data(), array.data());
+ }
+
+ // Unshare, must detach
+ array.setSharable(false);
+
+ // Immutability (alloc == 0) is lost on detach
+ if (capacity == 0 && size != 0)
+ capacity = size;
+
+ QVERIFY(!array->ref.isShared());
+ QVERIFY(!array->ref.isSharable());
+
+ QCOMPARE(size_t(array->size), size);
+ QCOMPARE(size_t(array->alloc), capacity);
+ QCOMPARE(bool(array->capacityReserved), isCapacityReserved);
+ QVERIFY(arrayIsFilledWith(array, fillValue, size));
+
+ {
+ QArrayDataPointer<int> copy(array);
+ QVERIFY(!array->ref.isShared());
+ QVERIFY(!array->ref.isSharable());
+
+ // Null/empty is always shared
+ QCOMPARE(copy->ref.isShared(), !(size || isCapacityReserved));
+ QVERIFY(copy->ref.isSharable());
+
+ QCOMPARE(size_t(copy->size), size);
+ QCOMPARE(size_t(copy->alloc), capacity);
+ QCOMPARE(bool(copy->capacityReserved), isCapacityReserved);
+ QVERIFY(arrayIsFilledWith(copy, fillValue, size));
+ }
+
+ // Make sharable, again
+ array.setSharable(true);
+
+ QCOMPARE(array->ref.isShared(), !(size || isCapacityReserved));
+ QVERIFY(array->ref.isSharable());
+
+ QCOMPARE(size_t(array->size), size);
+ QCOMPARE(size_t(array->alloc), capacity);
+ QCOMPARE(bool(array->capacityReserved), isCapacityReserved);
+ QVERIFY(arrayIsFilledWith(array, fillValue, size));
+
+ {
+ QArrayDataPointer<int> copy(array);
+ QVERIFY(array->ref.isShared());
+ QCOMPARE(copy.data(), array.data());
+ }
+
+ QCOMPARE(array->ref.isShared(), !(size || isCapacityReserved));
+ QVERIFY(array->ref.isSharable());
+}
+
+void tst_QArrayData::fromRawData()
+{
+ static const int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ {
+ // Default: Immutable, sharable
+ SimpleVector<int> raw = SimpleVector<int>::fromRawData(array,
+ sizeof(array)/sizeof(array[0]), QArrayData::Default);
+
+ QCOMPARE(raw.size(), size_t(11));
+ QCOMPARE(raw.constBegin(), array);
+ QCOMPARE((void *)raw.constEnd(), (void *)(array + sizeof(array)/sizeof(array[0])));
+
+ QVERIFY(!raw.isShared());
+ QVERIFY(SimpleVector<int>(raw).isSharedWith(raw));
+ QVERIFY(!raw.isShared());
+
+ // Detach
+ QCOMPARE(raw.back(), 11);
+ QVERIFY(raw.constBegin() != array);
+ }
+
+ {
+ // Immutable, unsharable
+ SimpleVector<int> raw = SimpleVector<int>::fromRawData(array,
+ sizeof(array)/sizeof(array[0]), QArrayData::Unsharable);
+
+ QCOMPARE(raw.size(), size_t(11));
+ QCOMPARE(raw.constBegin(), array);
+ QCOMPARE((void *)raw.constEnd(), (void *)(array + sizeof(array)/sizeof(array[0])));
+
+ SimpleVector<int> copy(raw);
+ QVERIFY(!copy.isSharedWith(raw));
+ QVERIFY(!raw.isShared());
+
+ QCOMPARE(copy.size(), size_t(11));
+
+ for (size_t i = 0; i < 11; ++i)
+ QCOMPARE(const_(copy)[i], const_(raw)[i]);
+
+ QCOMPARE(raw.size(), size_t(11));
+ QCOMPARE(raw.constBegin(), array);
+ QCOMPARE((void *)raw.constEnd(), (void *)(array + sizeof(array)/sizeof(array[0])));
+
+ // Detach
+ QCOMPARE(raw.back(), 11);
+ QVERIFY(raw.constBegin() != array);
+ }
+}
+
+void tst_QArrayData::literals()
+{
+ {
+ QArrayDataPointer<char> d = Q_ARRAY_LITERAL(char, "ABCDEFGHIJ");
+ QCOMPARE(d->size, 10 + 1);
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(d->data()[i], char('A' + i));
+ }
+
+ {
+ // wchar_t is not necessarily 2-bytes
+ QArrayDataPointer<wchar_t> d = Q_ARRAY_LITERAL(wchar_t, L"ABCDEFGHIJ");
+ QCOMPARE(d->size, 10 + 1);
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(d->data()[i], wchar_t('A' + i));
+ }
+
+ {
+ SimpleVector<char> v = Q_ARRAY_LITERAL(char, "ABCDEFGHIJ");
+
+ QVERIFY(!v.isNull());
+ QVERIFY(!v.isEmpty());
+ QCOMPARE(v.size(), size_t(11));
+ // v.capacity() is unspecified, for now
+
+#if defined(Q_COMPILER_VARIADIC_MACROS) \
+ && (defined(Q_COMPILER_LAMBDA) || defined(Q_CC_GNU))
+ QVERIFY(v.isStatic());
+#endif
+
+ QVERIFY(v.isSharable());
+ QCOMPARE((void *)(v.constBegin() + v.size()), (void *)v.constEnd());
+
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(const_(v)[i], char('A' + i));
+ QCOMPARE(const_(v)[10], char('\0'));
+ }
+}
+
+void tst_QArrayData::variadicLiterals()
+{
+#if defined(Q_COMPILER_VARIADIC_MACROS) \
+ && (defined(Q_COMPILER_LAMBDA) || defined(Q_CC_GNU))
+ {
+ QArrayDataPointer<int> d =
+ Q_ARRAY_LITERAL(int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ QCOMPARE(d->size, 10);
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(d->data()[i], i);
+ }
+
+ {
+ QArrayDataPointer<char> d = Q_ARRAY_LITERAL(char,
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
+ QCOMPARE(d->size, 10);
+ for (int i = 0; i < 10; ++i)
+ QCOMPARE(d->data()[i], char('A' + i));
+ }
+
+ {
+ QArrayDataPointer<const char *> d = Q_ARRAY_LITERAL(const char *,
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
+ QCOMPARE(d->size, 10);
+ for (int i = 0; i < 10; ++i) {
+ QCOMPARE(d->data()[i][0], char('A' + i));
+ QCOMPARE(d->data()[i][1], '\0');
+ }
+ }
+
+ {
+ SimpleVector<int> v = Q_ARRAY_LITERAL(int, 0, 1, 2, 3, 4, 5, 6);
+
+ QVERIFY(!v.isNull());
+ QVERIFY(!v.isEmpty());
+ QCOMPARE(v.size(), size_t(7));
+ // v.capacity() is unspecified, for now
+
+ QVERIFY(v.isStatic());
+
+ QVERIFY(v.isSharable());
+ QCOMPARE((void *)(v.constBegin() + v.size()), (void *)v.constEnd());
+
+ for (int i = 0; i < 7; ++i)
+ QCOMPARE(const_(v)[i], i);
+ }
+#else
+ QSKIP("Variadic Q_ARRAY_LITERAL not available in current configuration.");
+#endif // defined(Q_COMPILER_VARIADIC_MACROS)
+}
+
+#ifdef Q_COMPILER_RVALUE_REFS
+// std::remove_reference is in C++11, but requires library support
+template <class T> struct RemoveReference { typedef T Type; };
+template <class T> struct RemoveReference<T &> { typedef T Type; };
+
+// single-argument std::move is in C++11, but requires library support
+template <class T>
+typename RemoveReference<T>::Type &&cxx11Move(T &&t)
+{
+ return static_cast<typename RemoveReference<T>::Type &&>(t);
+}
+
+struct CompilerHasCxx11ImplicitMoves
+{
+ static bool value()
+ {
+ DetectImplicitMove d(cxx11Move(DetectImplicitMove()));
+ return d.constructor == DetectConstructor::MoveConstructor;
+ }
+
+ struct DetectConstructor
+ {
+ Q_DECL_CONSTEXPR DetectConstructor()
+ : constructor(DefaultConstructor)
+ {
+ }
+
+ Q_DECL_CONSTEXPR DetectConstructor(const DetectConstructor &)
+ : constructor(CopyConstructor)
+ {
+ }
+
+ Q_DECL_CONSTEXPR DetectConstructor(DetectConstructor &&)
+ : constructor(MoveConstructor)
+ {
+ }
+
+ enum Constructor {
+ DefaultConstructor,
+ CopyConstructor,
+ MoveConstructor
+ };
+
+ Constructor constructor;
+ };
+
+ struct DetectImplicitMove
+ : DetectConstructor
+ {
+ };
+};
+#endif
+
+void tst_QArrayData::rValueReferences()
+{
+#ifdef Q_COMPILER_RVALUE_REFS
+ if (!CompilerHasCxx11ImplicitMoves::value())
+ QSKIP("Implicit move ctor not supported in current configuration");
+
+ SimpleVector<int> v1(1, 42);
+ SimpleVector<int> v2;
+
+ const SimpleVector<int>::const_iterator begin = v1.constBegin();
+
+ QVERIFY(!v1.isNull());
+ QVERIFY(v2.isNull());
+
+ // move-assign
+ v2 = cxx11Move(v1);
+
+ QVERIFY(v1.isNull());
+ QVERIFY(!v2.isNull());
+ QCOMPARE(v2.constBegin(), begin);
+
+ SimpleVector<int> v3(cxx11Move(v2));
+
+ QVERIFY(v1.isNull());
+ QVERIFY(v2.isNull());
+ QVERIFY(!v3.isNull());
+ QCOMPARE(v3.constBegin(), begin);
+
+ QCOMPARE(v3.size(), size_t(1));
+ QCOMPARE(v3.front(), 42);
+#else
+ QSKIP("RValue references are not supported in current configuration");
+#endif
+}
+
+void tst_QArrayData::grow()
+{
+ SimpleVector<int> vector;
+
+ QCOMPARE(vector.size(), size_t(0));
+
+ size_t previousCapacity = vector.capacity();
+ size_t allocations = 0;
+ for (size_t i = 1; i <= (1 << 20); ++i) {
+ int source[1] = { int(i) };
+ vector.append(source, source + 1);
+ QCOMPARE(vector.size(), i);
+ if (vector.capacity() != previousCapacity) {
+ previousCapacity = vector.capacity();
+ ++allocations;
+ }
+ }
+ QCOMPARE(vector.size(), size_t(1 << 20));
+
+ // QArrayData::Grow prevents excessive allocations on a growing container
+ QVERIFY(allocations > 20 / 2);
+ QVERIFY(allocations < 20 * 2);
+
+ for (size_t i = 0; i < (1 << 20); ++i)
+ QCOMPARE(const_(vector).at(i), int(i + 1));
+}
+
+QTEST_APPLESS_MAIN(tst_QArrayData)
+#include "tst_qarraydata.moc"
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
index 5e53683abd..13a6b3d471 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
@@ -1078,18 +1078,25 @@ void tst_QByteArray::toULongLong()
// global function defined in qbytearray.cpp
void tst_QByteArray::qAllocMore()
{
- static const int t[] = {
- INT_MIN, INT_MIN + 1, -1234567, -66000, -1025,
- -3, -1, 0, +1, +3, +1025, +66000, +1234567, INT_MAX - 1, INT_MAX,
- INT_MAX/3
- };
- static const int N = sizeof(t)/sizeof(t[0]);
-
- // make sure qAllocMore() doesn't loop infinitely on any input
- for (int i = 0; i < N; ++i) {
- for (int j = 0; j < N; ++j) {
- ::qAllocMore(t[i], t[j]);
- }
+ using QT_PREPEND_NAMESPACE(qAllocMore);
+
+ // Not very important, but please behave :-)
+ QVERIFY(qAllocMore(0, 0) >= 0);
+
+ for (int i = 1; i < 1 << 8; i <<= 1)
+ QVERIFY(qAllocMore(i, 0) >= i);
+
+ for (int i = 1 << 8; i < 1 << 30; i <<= 1) {
+ const int alloc = qAllocMore(i, 0);
+
+ QVERIFY(alloc >= i);
+ QCOMPARE(qAllocMore(i - 8, 8), alloc - 8);
+ QCOMPARE(qAllocMore(i - 16, 16), alloc - 16);
+ QCOMPARE(qAllocMore(i - 24, 24), alloc - 24);
+ QCOMPARE(qAllocMore(i - 32, 32), alloc - 32);
+
+ QVERIFY(qAllocMore(i - 1, 0) >= i - 1);
+ QVERIFY(qAllocMore(i + 1, 0) >= i + 1);
}
}
@@ -1587,8 +1594,8 @@ void tst_QByteArray::literals()
QVERIFY(str.length() == 4);
QVERIFY(str == "abcd");
- QVERIFY(str.data_ptr()->ref == -1);
- QVERIFY(str.data_ptr()->offset == 0);