From 1b1337601e40da73cfb7ad463b3651070130268e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Sun, 8 May 2011 10:53:56 +0200 Subject: Fix the wayland windowsurface so that we have stencil and depth buffer (cherry picked from commit 322c96eb9564f930a63be820c22b053630663880) Change-Id: I89c10cea1a302d9549024940e49c7d5960abb953 Reviewed-on: http://codereview.qt.nokia.com/1210 Reviewed-by: Qt Sanity Bot Reviewed-by: Paul Olav Tvete --- .../platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp index a638fccf1e..fef07e6bf7 100644 --- a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp @@ -178,7 +178,7 @@ void QWaylandGLWindowSurface::resize(const QSize &size) QWindowSurface::resize(size); window()->platformWindow()->glContext()->makeCurrent(); delete mPaintDevice; - mPaintDevice = new QGLFramebufferObject(size); + mPaintDevice = new QGLFramebufferObject(size,QGLFramebufferObject::CombinedDepthStencil); } QT_END_NAMESPACE -- cgit v1.2.3 From 5d9818e7b61ca47a1566ba15baed647879d9dcda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 27 May 2011 02:12:02 -0700 Subject: We need to let the currentContext be in the same state after setting the new eglsurface (cherry picked from commit af3efefeefe686e5c35ed502de077c0bcb6f6fc0) Change-Id: Ic1d62b21a1482d1bc7f1d99478e175e4b767e157 Reviewed-on: http://codereview.qt.nokia.com/1209 Reviewed-by: Qt Sanity Bot Reviewed-by: Paul Olav Tvete --- .../wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp index 72ad5a8b6a..0f27501c71 100644 --- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp @@ -115,8 +115,15 @@ void *QWaylandGLContext::getProcAddress(const QString &string) void QWaylandGLContext::setEglSurface(EGLSurface surface) { - doneCurrent(); + bool wasCurrent = false; + if (QPlatformGLContext::currentContext() == this) { + wasCurrent = true; + doneCurrent(); + } mSurface = surface; + if (wasCurrent) { + makeCurrent(); + } } EGLConfig QWaylandGLContext::eglConfig() const -- cgit v1.2.3 From f306d18fe6555a9a5c60560745773b0bf5685ec3 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 5 Jul 2011 18:30:35 +0200 Subject: Remove QT3_SUPPORT from qsql, qxml Change-Id: Iab36ef60de2f0201efa4eb86d8ed5e514d6244fb Reviewed-on: http://codereview.qt.nokia.com/1188 Reviewed-by: Qt Sanity Bot Reviewed-by: Lars Knoll --- src/sql/kernel/qsql.h | 19 ----------- src/sql/kernel/qsqldatabase.cpp | 20 ------------ src/sql/kernel/qsqldatabase.h | 9 ------ src/sql/kernel/qsqldriver.h | 14 -------- src/sql/kernel/qsqlerror.h | 7 ---- src/sql/kernel/qsqlfield.h | 4 --- src/sql/kernel/qsqlindex.cpp | 54 ------------------------------- src/sql/kernel/qsqlindex.h | 8 ----- src/sql/kernel/qsqlquery.h | 3 -- src/sql/kernel/qsqlrecord.cpp | 71 ----------------------------------------- src/sql/kernel/qsqlrecord.h | 9 ------ src/sql/kernel/qsqlresult.h | 4 --- src/xml/sax/qxml.cpp | 23 ------------- src/xml/sax/qxml.h | 5 --- 14 files changed, 250 deletions(-) (limited to 'src') diff --git a/src/sql/kernel/qsql.h b/src/sql/kernel/qsql.h index 5a1c32381d..f23b518bfb 100644 --- a/src/sql/kernel/qsql.h +++ b/src/sql/kernel/qsql.h @@ -56,10 +56,6 @@ namespace QSql { BeforeFirstRow = -1, AfterLastRow = -2 -#ifdef QT3_SUPPORT - , BeforeFirst = BeforeFirstRow, - AfterLast = AfterLastRow -#endif }; enum ParamTypeFlag @@ -87,21 +83,6 @@ namespace QSql HighPrecision = 0 }; - -#ifdef QT3_SUPPORT - enum Op { - None = -1, - Insert = 0, - Update = 1, - Delete = 2 - }; - - enum Confirm { - Cancel = -1, - No = 0, - Yes = 1 - }; -#endif } Q_DECLARE_OPERATORS_FOR_FLAGS(QSql::ParamType) diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index c5eac194f5..cd36d5d591 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -1434,26 +1434,6 @@ bool QSqlDatabase::isValid() const return d->driver && d->driver != d->shared_null()->driver; } -#ifdef QT3_SUPPORT -/*! - Use query.record() instead. -*/ -QSqlRecord QSqlDatabase::record(const QSqlQuery& query) const -{ return query.record(); } - -/*! - Use query.record() instead. -*/ -QSqlRecord QSqlDatabase::recordInfo(const QSqlQuery& query) const -{ return query.record(); } - -/*! - \fn QSqlRecord QSqlDatabase::recordInfo(const QString& tablename) const - - Use record() instead. -*/ -#endif - /*! Clones the database connection \a other and and stores it as \a connectionName. All the settings from the original database, e.g. diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h index c8cde8557e..72c5694ceb 100644 --- a/src/sql/kernel/qsqldatabase.h +++ b/src/sql/kernel/qsqldatabase.h @@ -44,9 +44,6 @@ #include #include -#ifdef QT3_SUPPORT -#include -#endif QT_BEGIN_HEADER @@ -92,12 +89,6 @@ public: QStringList tables(QSql::TableType type = QSql::Tables) const; QSqlIndex primaryIndex(const QString& tablename) const; QSqlRecord record(const QString& tablename) const; -#ifdef QT3_SUPPORT - QT3_SUPPORT QSqlRecord record(const QSqlQuery& query) const; - inline QT3_SUPPORT QSqlRecord recordInfo(const QString& tablename) const - { return record(tablename); } - QT3_SUPPORT QSqlRecord recordInfo(const QSqlQuery& query) const; -#endif QSqlQuery exec(const QString& query = QString()) const; QSqlError lastError() const; bool isValid() const; diff --git a/src/sql/kernel/qsqldriver.h b/src/sql/kernel/qsqldriver.h index 479d3ac990..ee1e52538a 100644 --- a/src/sql/kernel/qsqldriver.h +++ b/src/sql/kernel/qsqldriver.h @@ -46,9 +46,6 @@ #include #include #include -#ifdef QT3_SUPPORT -#include -#endif QT_BEGIN_HEADER @@ -93,17 +90,6 @@ public: virtual QStringList tables(QSql::TableType tableType) const; virtual QSqlIndex primaryIndex(const QString &tableName) const; virtual QSqlRecord record(const QString &tableName) const; -#ifdef QT3_SUPPORT - inline QT3_SUPPORT QSqlRecord record(const QSqlQuery& query) const - { return query.record(); } - inline QT3_SUPPORT QSqlRecord recordInfo(const QString& tablename) const - { return record(tablename); } - inline QT3_SUPPORT QSqlRecord recordInfo(const QSqlQuery& query) const - { return query.record(); } - inline QT3_SUPPORT QString nullText() const { return QLatin1String("NULL"); } - inline QT3_SUPPORT QString formatValue(const QSqlField *field, bool trimStrings = false) const - { return field ? formatValue(*field, trimStrings) : QString(); } -#endif virtual QString formatValue(const QSqlField& field, bool trimStrings = false) const; virtual QString escapeIdentifier(const QString &identifier, IdentifierType type) const; diff --git a/src/sql/kernel/qsqlerror.h b/src/sql/kernel/qsqlerror.h index 87136ecda9..fea3ca8526 100644 --- a/src/sql/kernel/qsqlerror.h +++ b/src/sql/kernel/qsqlerror.h @@ -59,13 +59,6 @@ public: StatementError, TransactionError, UnknownError -#ifdef QT3_SUPPORT - , None = NoError, - Connection = ConnectionError, - Statement = StatementError, - Transaction = TransactionError, - Unknown = UnknownError -#endif }; QSqlError( const QString& driverText = QString(), const QString& databaseText = QString(), diff --git a/src/sql/kernel/qsqlfield.h b/src/sql/kernel/qsqlfield.h index 182b5318e2..93992ea9d4 100644 --- a/src/sql/kernel/qsqlfield.h +++ b/src/sql/kernel/qsqlfield.h @@ -98,10 +98,6 @@ public: bool isGenerated() const; bool isValid() const; -#ifdef QT3_SUPPORT - inline QT3_SUPPORT void setNull() { clear(); } -#endif - private: void detach(); QVariant val; diff --git a/src/sql/kernel/qsqlindex.cpp b/src/sql/kernel/qsqlindex.cpp index 33e3c1ce34..764e93a678 100644 --- a/src/sql/kernel/qsqlindex.cpp +++ b/src/sql/kernel/qsqlindex.cpp @@ -164,60 +164,6 @@ void QSqlIndex::setDescending(int i, bool desc) sorts[i] = desc; } -#ifdef QT3_SUPPORT - -/*! - Returns a comma-separated list of all the index's field names as a - string. This string is suitable, for example, for generating a - SQL SELECT statement. Only generated fields are included in the - list (see \l{isGenerated()}). If a \a prefix is specified, e.g. a - table name, it is prepended before all field names in the form: - - "\a{prefix}." - - If \a sep is specified, each field is separated by \a sep. If \a - verbose is true (the default), each field contains a suffix - indicating an ASCending or DESCending sort order. -*/ - -QString QSqlIndex::toString(const QString& prefix, const QString& sep, bool verbose) const -{ - QString s; - bool comma = false; - for (int i = 0; i < count(); ++i) { - if(comma) - s += sep + QLatin1Char(' '); - s += createField(i, prefix, verbose); - comma = true; - } - return s; -} - -/*! - Returns a list of all the index's field names. Only generated - fields are included in the list (see \l{isGenerated()}). If a \a - prefix is specified, e.g. a table name, all fields are prefixed in - the form: - - "\a{prefix}." - - If \a verbose is true (the default), each field contains a suffix - indicating an ASCending or DESCending sort order. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_sql_kernel_qsqlindex.cpp 0 - -*/ -QStringList QSqlIndex::toStringList(const QString& prefix, bool verbose) const -{ - QStringList s; - for (int i = 0; i < count(); ++i) - s += createField(i, prefix, verbose); - return s; -} -#endif - /*! \internal Creates a string representing the field number \a i using prefix \a diff --git a/src/sql/kernel/qsqlindex.h b/src/sql/kernel/qsqlindex.h index 97874e24f6..c88e30603f 100644 --- a/src/sql/kernel/qsqlindex.h +++ b/src/sql/kernel/qsqlindex.h @@ -70,14 +70,6 @@ public: bool isDescending(int i) const; void setDescending(int i, bool desc); -#ifdef QT3_SUPPORT - QT3_SUPPORT QString toString(const QString &prefix = QString(), - const QString &sep = QLatin1String(","), - bool verbose = true) const; - QT3_SUPPORT QStringList toStringList(const QString& prefix = QString(), - bool verbose = true) const; -#endif - private: QString createField(int i, const QString& prefix, bool verbose) const; QString cursor; diff --git a/src/sql/kernel/qsqlquery.h b/src/sql/kernel/qsqlquery.h index e82380956c..bd498f344a 100644 --- a/src/sql/kernel/qsqlquery.h +++ b/src/sql/kernel/qsqlquery.h @@ -94,9 +94,6 @@ public: bool seek(int i, bool relative = false); bool next(); bool previous(); -#ifdef QT3_SUPPORT - inline QT3_SUPPORT bool prev() { return previous(); } -#endif bool first(); bool last(); diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp index dfeb3e0622..944f2fc9bc 100644 --- a/src/sql/kernel/qsqlrecord.cpp +++ b/src/sql/kernel/qsqlrecord.cpp @@ -244,34 +244,6 @@ int QSqlRecord::indexOf(const QString& name) const return -1; } -#ifdef QT3_SUPPORT -/*! - \obsolete - Use field() instead -*/ -const QSqlField* QSqlRecord::fieldPtr(int index) const -{ - if (!d->contains(index)) - return 0; - - return &d->fields.at(index); -} - -/*! - \obsolete - Use field() instead -*/ - -const QSqlField* QSqlRecord::fieldPtr(const QString& name) const -{ - int i = indexOf(name); - if (!d->contains(i)) - return 0; - - return &d->fields.at(i); -} -#endif //QT3_SUPPORT - /*! Returns the field at position \a index. If the position is out of range, an empty field is returned. @@ -496,49 +468,6 @@ bool QSqlRecord::isGenerated(int index) const return d->fields.value(index).isGenerated(); } -#ifdef QT3_SUPPORT -/*! - Returns a list of all the record's field names as a string - separated by \a sep. - - In the unlikely event that you used this function in Qt 3, you - can simulate it using the rest of the QSqlRecord public API. -*/ - -QString QSqlRecord::toString(const QString& prefix, const QString& sep) const -{ - QString pflist; - bool comma = false; - for (int i = 0; i < count(); ++i) { - if (!d->fields.value(i).isGenerated()) { - if (comma) - pflist += sep + QLatin1Char(' '); - pflist += d->createField(i, prefix); - comma = true; - } - } - return pflist; -} - -/*! - Returns a list of all the record's field names, each having the - prefix \a prefix. - - In the unlikely event that you used this function in Qt 3, you - can simulate it using the rest of the QSqlRecord public API. -*/ - -QStringList QSqlRecord::toStringList(const QString& prefix) const -{ - QStringList s; - for (int i = 0; i < count(); ++i) { - if (!d->fields.value(i).isGenerated()) - s += d->createField(i, prefix); - } - return s; -} -#endif // QT3_SUPPORT - /*! Returns the number of fields in the record. diff --git a/src/sql/kernel/qsqlrecord.h b/src/sql/kernel/qsqlrecord.h index e697e8e170..8c7a17ab1d 100644 --- a/src/sql/kernel/qsqlrecord.h +++ b/src/sql/kernel/qsqlrecord.h @@ -87,15 +87,6 @@ public: void setGenerated(const QString& name, bool generated); void setGenerated(int i, bool generated); -#ifdef QT3_SUPPORT - QT3_SUPPORT const QSqlField* fieldPtr(int i) const; - QT3_SUPPORT const QSqlField* fieldPtr(const QString& name) const; - inline QT3_SUPPORT int position(const QString& name) const { return indexOf(name); } - QT3_SUPPORT QString toString(const QString& prefix = QString(), - const QString& sep = QLatin1String(",")) const; - QT3_SUPPORT QStringList toStringList(const QString& prefix = QString()) const; -#endif - void append(const QSqlField& field); void replace(int pos, const QSqlField& field); void insert(int pos, const QSqlField& field); diff --git a/src/sql/kernel/qsqlresult.h b/src/sql/kernel/qsqlresult.h index 58b19c193d..984bd5e03f 100644 --- a/src/sql/kernel/qsqlresult.h +++ b/src/sql/kernel/qsqlresult.h @@ -74,10 +74,6 @@ protected: enum BindingSyntax { PositionalBinding, NamedBinding -#ifdef QT3_SUPPORT - , BindByPosition = PositionalBinding, - BindByName = NamedBinding -#endif }; explicit QSqlResult(const QSqlDriver * db); diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 2f5384b902..671adafcbd 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -1324,29 +1324,6 @@ QXmlInputSource::QXmlInputSource(QIODevice *dev) d->inputDevice->setTextModeEnabled(false); } -#ifdef QT3_SUPPORT -/*! - Use the QXmlInputSource(QIODevice *) constructor instead, with - the device used by \a stream. - - \sa QTextStream::device() -*/ -QXmlInputSource::QXmlInputSource(QTextStream& stream) -{ - init(); - d->inputStream = &stream; -} - -/*! - Use QXmlInputSource(&\a file) instead. -*/ -QXmlInputSource::QXmlInputSource(QFile& file) -{ - init(); - d->inputDevice = &file; -} -#endif - /*! Destructor. */ diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h index 8b402dfedb..52eea6ce76 100644 --- a/src/xml/sax/qxml.h +++ b/src/xml/sax/qxml.h @@ -172,11 +172,6 @@ public: static const ushort EndOfData; static const ushort EndOfDocument; -#ifdef QT3_SUPPORT - QT3_SUPPORT_CONSTRUCTOR QXmlInputSource(QFile& file); - QT3_SUPPORT_CONSTRUCTOR QXmlInputSource(QTextStream& stream); -#endif - protected: virtual QString fromRawData(const QByteArray &data, bool beginning = false); -- cgit v1.2.3 From 26a6d3f11b5a88fb2b6564384429eadffc3f16c3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 4 Jul 2011 14:03:23 +0200 Subject: Fix compilation with c++0x mode Change-Id: Ie4f157f25c31e46d4cc7cb628b8605b99561a4e8 Reviewed-on: http://codereview.qt.nokia.com/1220 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/tools/qstringlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index efb7f46c9b..bded94399d 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -68,7 +68,7 @@ public: inline QStringList(const QStringList &l) : QList(l) { } inline QStringList(const QList &l) : QList(l) { } #ifdef Q_COMPILER_INITIALIZER_LISTS - inline QStringList(std::initializer_list args) : QList(args) { } + inline QStringList(std::initializer_list args) : QList(args) { } #endif inline void sort(); -- cgit v1.2.3 From a97d4dcb24a9fc69ee57c5607005a4e8b85d3b32 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Mon, 4 Jul 2011 10:30:18 +0200 Subject: Remove references to QT_INSTALL_DEMOS & DemosPath. The distinction between 'examples' and 'demos' is completely blurred at this point. We've decided, with the SDK people, to scrap the existing terminology in favor of the word 'example' only -- distinguishing between code snippets, walkthroughs, "demonstrations" can be done via keywords or some other method. Removing QT_INSTALL_DEMOS from all .pro files in Qt is still in progress. Change-Id: I86fc0e40d54baa54c5641fc6acbd8b67e4ad2789 Reviewed-on: http://codereview.qt.nokia.com/1034 Reviewed-by: Qt Sanity Bot Reviewed-by: Marius Storm-Olsen --- src/corelib/global/qlibraryinfo.cpp | 9 --------- src/corelib/global/qlibraryinfo.h | 1 - 2 files changed, 10 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 5333b71d7b..88f12ab1f7 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -296,11 +296,6 @@ QLibraryInfo::location(LibraryLocation loc) case ExamplesPath: path = QT_CONFIGURE_EXAMPLES_PATH; break; -#endif -#ifdef QT_CONFIGURE_DEMOS_PATH - case DemosPath: - path = QT_CONFIGURE_DEMOS_PATH; - break; #endif default: break; @@ -352,9 +347,6 @@ QLibraryInfo::location(LibraryLocation loc) case ExamplesPath: key = QLatin1String("Examples"); break; - case DemosPath: - key = QLatin1String("Demos"); - break; default: break; } @@ -500,7 +492,6 @@ QLibraryInfo::location(LibraryLocation loc) \value TranslationsPath The location of translation information for Qt strings. \value SettingsPath The location for Qt settings. \value ExamplesPath The location for examples upon install. - \value DemosPath The location for demos upon install. \sa location() */ diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 9af53c315c..a8fb90968c 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -75,7 +75,6 @@ public: DataPath, TranslationsPath, SettingsPath, - DemosPath, ExamplesPath, ImportsPath }; -- cgit v1.2.3 From 3422bc3b186a32ae985d3130090b71305380bbd6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 6 Jul 2011 09:20:45 +0200 Subject: Unicode strings are supported from gcc 4.4 onwards Change-Id: Icf3dfdb34b0a9867c69e91e5eb8400aa934f56bc Reviewed-on: http://codereview.qt.nokia.com/1217 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/global/qglobal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 204652f7c1..fda771e8ab 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -525,6 +525,7 @@ namespace QT_NAMESPACE {} # endif # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 /* C++0x features supported in GCC 4.4: */ +# define Q_COMPILER_UNICODE_STRINGS # define Q_COMPILER_VARIADIC_TEMPLATES # define Q_COMPILER_AUTO_TYPE # define Q_COMPILER_EXTERN_TEMPLATES @@ -535,7 +536,6 @@ namespace QT_NAMESPACE {} # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 /* C++0x features supported in GCC 4.5: */ # define Q_COMPILER_LAMBDA -# define Q_COMPILER_UNICODE_STRINGS # endif # endif @@ -976,6 +976,7 @@ QT_END_INCLUDE_NAMESPACE #error "Compiler doesn't support the bool type" #endif + /* Constant bool values */ -- cgit v1.2.3 From febb4b8df382352596ac814e9d69a4548c56208f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 6 Jul 2011 11:44:57 +0200 Subject: Fix bidi reordering when part of text is rendered by fallback font If the fallback font is used for part of a RTL text, we need to position the different text items accordingly, subtracting the advance instead of adding it. Task-number: QTBUG-17117 Done-with: Lars (cherry picked from commit e5e1ff0d6f4e6a8457da61b5b215730de6f960bd) Change-Id: I73b501d36e5c9e12112cc1997c1d360f3a4a6083 Reviewed-on: http://codereview.qt.nokia.com/1228 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qpainter.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 6a4c7db7f0..8752cb86a7 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6629,6 +6629,10 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) qreal x = p.x(); qreal y = p.y(); + bool rtl = ti.flags & QTextItem::RightToLeft; + if (rtl) + x += ti.width.toReal(); + int start = 0; int end, i; for (end = 0; end < ti.glyphs.numGlyphs; ++end) { @@ -6645,14 +6649,19 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) ti2.width += ti.glyphs.effectiveAdvance(i); } + if (rtl) + x -= ti2.width.toReal(); + d->engine->drawTextItem(QPointF(x, y), ti2); + if (!rtl) + x += ti2.width.toReal(); + // reset the high byte for all glyphs and advance to the next sub-string const int hi = which << 24; for (i = start; i < end; ++i) { glyphs.glyphs[i] = hi | glyphs.glyphs[i]; } - x += ti2.width.toReal(); // change engine start = end; @@ -6667,6 +6676,9 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) ti2.width += ti.glyphs.effectiveAdvance(i); } + if (rtl) + x -= ti2.width.toReal(); + if (d->extended) d->extended->drawTextItem(QPointF(x, y), ti2); else -- cgit v1.2.3 From 28f927f8e092a02e233559f6da7fa96cf722c77d Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 6 Jul 2011 16:35:04 +0200 Subject: Add Q_DECL_CONSTEXPR Defined to the c++0x constexpr when compiler supports it Change-Id: I82687fe46848eedf3cffc39982106749b3dde8aa Reviewed-on: http://codereview.qt.nokia.com/1247 Reviewed-by: Qt Sanity Bot Reviewed-by: Gabriel de Dietrich --- src/corelib/global/qglobal.h | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index fda771e8ab..85a54fc362 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -537,6 +537,11 @@ namespace QT_NAMESPACE {} /* C++0x features supported in GCC 4.5: */ # define Q_COMPILER_LAMBDA # endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + /* C++0x features supported in GCC 4.6: */ +# define Q_COMPILER_CONSTEXPR +# endif + # endif /* IBM compiler versions are a bit messy. There are actually two products: @@ -1107,6 +1112,12 @@ redefine to built-in booleans to make autotests work properly */ # define QT_FASTCALL #endif +#ifdef Q_COMPILER_CONSTEXPR +# define Q_DECL_CONSTEXPR constexpr +#else +# define Q_DECL_CONSTEXPR +#endif + //defines the type for the WNDPROC on windows //the alignment needs to be forced for sse2 to not crash with mingw #if defined(Q_WS_WIN) @@ -1138,25 +1149,25 @@ typedef double qreal; */ template -inline T qAbs(const T &t) { return t >= 0 ? t : -t; } +Q_DECL_CONSTEXPR inline T qAbs(const T &t) { return t >= 0 ? t : -t; } -inline int qRound(qreal d) +Q_DECL_CONSTEXPR inline int qRound(qreal d) { return d >= qreal(0.0) ? int(d + qreal(0.5)) : int(d - int(d-1) + qreal(0.5)) + int(d-1); } #if defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN) -inline qint64 qRound64(double d) +Q_DECL_CONSTEXPR inline qint64 qRound64(double d) { return d >= 0.0 ? qint64(d + 0.5) : qint64(d - qreal(qint64(d-1)) + 0.5) + qint64(d-1); } #else -inline qint64 qRound64(qreal d) +Q_DECL_CONSTEXPR inline qint64 qRound64(qreal d) { return d >= qreal(0.0) ? qint64(d + qreal(0.5)) : qint64(d - qreal(qint64(d-1)) + qreal(0.5)) + qint64(d-1); } #endif template -inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; } +Q_DECL_CONSTEXPR inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; } template -inline const T &qMax(const T &a, const T &b) { if (a < b) return b; return a; } +Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; } template -inline const T &qBound(const T &min, const T &val, const T &max) +Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max) { return qMax(min, qMin(max, val)); } /* @@ -1915,12 +1926,12 @@ inline bool operator!=(QBool b1, bool b2) { return !b1 != !b2; } inline bool operator!=(bool b1, QBool b2) { return !b1 != !b2; } inline bool operator!=(QBool b1, QBool b2) { return !b1 != !b2; } -static inline bool qFuzzyCompare(double p1, double p2) +Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(double p1, double p2) { return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2))); } -static inline bool qFuzzyCompare(float p1, float p2) +Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(float p1, float p2) { return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2))); } @@ -1928,7 +1939,7 @@ static inline bool qFuzzyCompare(float p1, float p2) /*! \internal */ -static inline bool qFuzzyIsNull(double d) +Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(double d) { return qAbs(d) <= 0.000000000001; } @@ -1936,7 +1947,7 @@ static inline bool qFuzzyIsNull(double d) /*! \internal */ -static inline bool qFuzzyIsNull(float f) +Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(float f) { return qAbs(f) <= 0.00001f; } -- cgit v1.2.3 From c0c6dd2b022cfd667f32b8a48bcac86ac07d3880 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 6 Jul 2011 16:37:14 +0200 Subject: Use Q_DECL_CONSTEXPR in QFlags Change-Id: I851e0b1c3f80a7b33a38cb1ab2665dc0f3c73adc Reviewed-on: http://codereview.qt.nokia.com/1248 Reviewed-by: Qt Sanity Bot Reviewed-by: Gabriel de Dietrich --- src/corelib/global/qglobal.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 85a54fc362..6c89e9b670 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -2215,9 +2215,9 @@ class QFlags int i; public: typedef Enum enum_type; - inline QFlags(const QFlags &f) : i(f.i) {} - inline QFlags(Enum f) : i(f) {} - inline QFlags(Zero = 0) : i(0) {} + Q_DECL_CONSTEXPR inline QFlags(const QFlags &f) : i(f.i) {} + Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(f) {} + Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {} inline QFlags(QFlag f) : i(f) {} inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; } @@ -2228,18 +2228,18 @@ public: inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; } inline QFlags &operator^=(Enum f) { i ^= f; return *this; } - inline operator int() const { return i; } + Q_DECL_CONSTEXPR inline operator int() const { return i; } - inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i; return g; } - inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g; } - inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return g; } - inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g; } - inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask; return g; } - inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask; return g; } - inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; } - inline QFlags operator~() const { QFlags g; g.i = ~i; return g; } + Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); } + Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ f)); } + Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & f)); } + Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); } - inline bool operator!() const { return !i; } + Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); } }; @@ -2252,9 +2252,9 @@ inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \ { return QIncompatibleFlag(int(f1) | f2); } #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \ -inline QFlags operator|(Flags::enum_type f1, Flags::enum_type f2) \ +Q_DECL_CONSTEXPR inline QFlags operator|(Flags::enum_type f1, Flags::enum_type f2) \ { return QFlags(f1) | f2; } \ -inline QFlags operator|(Flags::enum_type f1, QFlags f2) \ +Q_DECL_CONSTEXPR inline QFlags operator|(Flags::enum_type f1, QFlags f2) \ { return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) -- cgit v1.2.3 From 1174b69ee13d372cb01fc351d5ba158a6909744c Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 7 Jul 2011 08:36:45 +0200 Subject: Fix regressions in previous QFontDatabase patch 1. QtFontStyle::Key comparison should either use styleName or style, etc., but not both. 2. When initializing a QFont from QFontDatabase::font(), style and weight parameters should always be set even when we found a match styleName, in case these parameters will be used for comparison later. 3. Move styleName out of QtFontStyle::Key so that the code can be clearer and more explicit. Change-Id: Icdee8e97568a0f31f57d2cdb8d414f47331fde75 Reviewed-by: Eskil Reviewed-on: http://codereview.qt.nokia.com/1263 Reviewed-by: Qt Sanity Bot Reviewed-by: Jiang Jiang --- src/gui/text/qfontdatabase.cpp | 93 ++++++++++++++++++++------------------ src/gui/text/qfontdatabase_mac.cpp | 6 +-- src/gui/text/qfontdatabase_qpa.cpp | 2 +- src/gui/text/qfontdatabase_s60.cpp | 2 +- src/gui/text/qfontdatabase_win.cpp | 8 ++-- src/gui/text/qfontdatabase_x11.cpp | 10 ++-- 6 files changed, 64 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 2a73223da1..d4e3cc25a2 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -218,17 +218,14 @@ struct QtFontStyle Key(const QString &styleString); Key() : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) { } - Key(const Key &o) : styleName(o.styleName), style(o.style), - weight(o.weight), stretch(o.stretch) { } - QString styleName; + Key(const Key &o) : style(o.style), weight(o.weight), stretch(o.stretch) { } uint style : 2; signed int weight : 8; signed int stretch : 12; bool operator==(const Key & other) { - return styleName == other.styleName && style == other.style && - weight == other.weight && - (stretch == 0 || other.stretch == 0 || stretch == other.stretch); + return (style == other.style && weight == other.weight && + (stretch == 0 || other.stretch == 0 || stretch == other.stretch)); } bool operator!=(const Key &other) { return !operator==(other); @@ -280,6 +277,7 @@ struct QtFontStyle bool smoothScalable : 1; signed int count : 30; QtFontSize *pixelSizes; + QString styleName; #ifdef Q_WS_X11 const char *weightName; @@ -293,7 +291,7 @@ struct QtFontStyle }; QtFontStyle::Key::Key(const QString &styleString) - : styleName(styleString), style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) + : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) { weight = getFontWeight(styleString); @@ -354,13 +352,20 @@ struct QtFontFoundry int count; QtFontStyle **styles; - QtFontStyle *style(const QtFontStyle::Key &, bool = false); + QtFontStyle *style(const QtFontStyle::Key &, const QString & = QString(), bool = false); }; -QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) +QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create) { int pos = 0; if (count) { + // if styleName for searching first if possible + if (!styleName.isEmpty()) { + for (; pos < count; pos++) { + if (styles[pos]->styleName == styleName) + return styles[pos]; + } + } int low = 0; int high = count; pos = count / 2; @@ -387,6 +392,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) } QtFontStyle *style = new QtFontStyle(key); + style->styleName = styleName; memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *)); styles[pos] = style; count++; @@ -815,7 +821,7 @@ void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundr } QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = (pixelSize == 0); style->antialiased = antialiased; QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); @@ -1132,7 +1138,8 @@ QString QFontDatabase::resolveFontFamilyAlias(const QString &family) } #endif -static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey) +static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey, + const QString &styleName = QString()) { int best = 0; int dist = 0xffff; @@ -1140,7 +1147,7 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st for ( int i = 0; i < foundry->count; i++ ) { QtFontStyle *style = foundry->styles[i]; - if (!styleKey.styleName.isEmpty() && styleKey.styleName == style->key.styleName) { + if (!styleName.isEmpty() && styleName == style->styleName) { dist = 0; best = i; break; @@ -1797,16 +1804,16 @@ QStringList QFontDatabase::styles(const QString &family) const for (int k = 0; k < foundry->count; k++) { QtFontStyle::Key ke(foundry->styles[k]->key); ke.stretch = 0; - allStyles.style(ke, true); + allStyles.style(ke, foundry->styles[k]->styleName, true); } } } for (int i = 0; i < allStyles.count; i++) { - l.append(allStyles.styles[i]->key.styleName.isEmpty() ? + l.append(allStyles.styles[i]->styleName.isEmpty() ? styleStringHelper(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style) : - allStyles.styles[i]->key.styleName); + allStyles.styles[i]->styleName); } return l; } @@ -1865,7 +1872,9 @@ bool QFontDatabase::isBitmapScalable(const QString &family, QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - if ((style.isEmpty() || foundry->styles[k]->key == styleKey) + if ((style.isEmpty() || + foundry->styles[k]->styleName == style || + foundry->styles[k]->key == styleKey) && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) { bitmapScalable = true; goto end; @@ -1904,7 +1913,9 @@ bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &sty QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) { + if ((style.isEmpty() || + foundry->styles[k]->styleName == style || + foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) { smoothScalable = true; goto end; } @@ -1937,12 +1948,12 @@ bool QFontDatabase::isScalable(const QString &family, \sa smoothSizes(), standardSizes() */ QList QFontDatabase::pointSizes(const QString &family, - const QString &style) + const QString &styleName) { #if defined(Q_WS_WIN) // windows and macosx are always smoothly scalable Q_UNUSED(family); - Q_UNUSED(style); + Q_UNUSED(styleName); return standardSizes(); #else bool smoothScalable = false; @@ -1953,7 +1964,7 @@ QList QFontDatabase::pointSizes(const QString &family, QT_PREPEND_NAMESPACE(load)(familyName); - QtFontStyle::Key styleKey(style); + QtFontStyle::Key styleKey(styleName); QList sizes; @@ -1970,7 +1981,7 @@ QList QFontDatabase::pointSizes(const QString &family, for (int j = 0; j < fam->count; j++) { QtFontFoundry *foundry = fam->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { - QtFontStyle *style = foundry->style(styleKey); + QtFontStyle *style = foundry->style(styleKey, styleName); if (!style) continue; if (style->smoothScalable) { @@ -2021,25 +2032,21 @@ QFont QFontDatabase::font(const QString &family, const QString &style, QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = bestStyle(&allStyles, styleKey); + QtFontStyle *s = bestStyle(&allStyles, styleKey, style); if (!s) // no styles found? return QApplication::font(); - if (s->key.styleName.isEmpty()) { - QFont fnt(family, pointSize, s->key.weight); - fnt.setStyle((QFont::Style)s->key.style); - return fnt; - } else { - // found a perfect match - QFont fnt(family, pointSize); - fnt.setStyleName(s->key.styleName); - return fnt; - } + + QFont fnt(family, pointSize, s->key.weight); + fnt.setStyle((QFont::Style)s->key.style); + if (!s->styleName.isEmpty()) + fnt.setStyleName(s->styleName); + return fnt; } @@ -2052,11 +2059,11 @@ QFont QFontDatabase::font(const QString &family, const QString &style, \sa pointSizes(), standardSizes() */ QList QFontDatabase::smoothSizes(const QString &family, - const QString &style) + const QString &styleName) { #ifdef Q_WS_WIN Q_UNUSED(family); - Q_UNUSED(style); + Q_UNUSED(styleName); return QFontDatabase::standardSizes(); #else bool smoothScalable = false; @@ -2067,7 +2074,7 @@ QList QFontDatabase::smoothSizes(const QString &family, QT_PREPEND_NAMESPACE(load)(familyName); - QtFontStyle::Key styleKey(style); + QtFontStyle::Key styleKey(styleName); QList sizes; @@ -2084,7 +2091,7 @@ QList QFontDatabase::smoothSizes(const QString &family, for (int j = 0; j < fam->count; j++) { QtFontFoundry *foundry = fam->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { - QtFontStyle *style = foundry->style(styleKey); + QtFontStyle *style = foundry->style(styleKey, styleName); if (!style) continue; if (style->smoothScalable) { @@ -2151,12 +2158,12 @@ bool QFontDatabase::italic(const QString &family, const QString &style) const QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = allStyles.style(styleKey); + QtFontStyle *s = allStyles.style(styleKey, style); return s && s->key.style == QFont::StyleItalic; } @@ -2186,12 +2193,12 @@ bool QFontDatabase::bold(const QString &family, if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = allStyles.style(styleKey); + QtFontStyle *s = allStyles.style(styleKey, style); return s && s->key.weight >= QFont::Bold; } @@ -2222,12 +2229,12 @@ int QFontDatabase::weight(const QString &family, if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = allStyles.style(styleKey); + QtFontStyle *s = allStyles.style(styleKey, style); return s ? s->key.weight : -1; } diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index b7335d684e..e1e59b79eb 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -113,7 +113,7 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QtFontFoundry *foundry = family->foundry(foundry_name, true); QtFontStyle::Key styleKey; - styleKey.styleName = style_name; + QString styleName = style_name; if(QCFType styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) { if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) { Q_ASSERT(CFNumberIsFloatType(weight)); @@ -134,7 +134,7 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { } } - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, styleName, true); style->smoothScalable = true; if(QCFType size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { //qDebug() << "WHEE"; @@ -207,7 +207,7 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QtFontFamily *family = db->family(familyName, true); QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->pixelSize(0, true); style->smoothScalable = true; diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index fd5c6b4510..6b6f4f1a54 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -73,7 +73,7 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &fou } QtFontFoundry *foundry = f->foundry(foundryname, true); - QtFontStyle *fontStyle = foundry->style(styleKey, true); + QtFontStyle *fontStyle = foundry->style(styleKey, QString(), true); fontStyle->smoothScalable = scalable; fontStyle->antialiased = antialiased; QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index eea075fc47..cfa405dbc1 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -508,7 +508,7 @@ static bool registerScreenDeviceFont(int screenDeviceFontIndex, QtFontFamily *family = privateDb()->family(familyName, true); family->fixedPitch = faceAttrib.IsMonoWidth(); QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = typefaceSupport.iIsScalable; style->pixelSize(0, true); diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp index 20f945a6c9..788eb307c3 100644 --- a/src/gui/text/qfontdatabase_win.cpp +++ b/src/gui/text/qfontdatabase_win.cpp @@ -284,7 +284,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName, family->english_name = getEnglishName(familyName); QtFontFoundry *foundry = family->foundry(foundryName, true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); @@ -292,14 +292,14 @@ void addFontToDatabase(QString familyName, const QString &scriptName, if (styleKey.weight <= QFont::DemiBold) { QtFontStyle::Key key(styleKey); key.weight = QFont::Bold; - QtFontStyle *style = foundry->style(key, true); + QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } if (styleKey.style != QFont::StyleItalic) { QtFontStyle::Key key(styleKey); key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, true); + QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } @@ -307,7 +307,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName, QtFontStyle::Key key(styleKey); key.weight = QFont::Bold; key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, true); + QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index ed94fa6be1..922a97f3aa 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -680,7 +680,7 @@ static void loadXlfds(const char *reqFamily, int encoding_id) family->fontFileIndex = -1; family->symbol_checked = true; QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); delete [] style->weightName; style->weightName = qstrdup(tokens[Weight]); @@ -1145,7 +1145,7 @@ static void loadFontConfig() family->fontFileIndex = index_value; QtFontStyle::Key styleKey; - styleKey.styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); + QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); styleKey.style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) @@ -1160,7 +1160,7 @@ static void loadFontConfig() QtFontFoundry *foundry = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, styleName, true); if (spacing_value < FC_MONO) family->fixedPitch = false; @@ -1212,7 +1212,7 @@ static void loadFontConfig() for (int i = 0; i < 4; ++i) { styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic; styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal; - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = true; QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true); QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); @@ -1360,7 +1360,7 @@ static void initializeDb() if (equiv) continue; // let's fake one... - equiv = foundry->style(key, true); + equiv = foundry->style(key, QString(), true); equiv->smoothScalable = true; QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true); -- cgit v1.2.3 From 2d802625a3279116f5a6c1ad9a04a51b1ae0b563 Mon Sep 17 00:00:00 2001 From: Jyri Tahtela Date: Tue, 5 Jul 2011 17:05:10 +0300 Subject: Update licenseheader text in source files for qtbase Qt module Replace old license header with correct one. Change-Id: Ie8bf7d8d07ff01d05654bafe13ebbc1892f59cc4 Reviewed-on: http://codereview.qt.nokia.com/1178 Reviewed-by: Rohan McGovern Reviewed-by: Jyri Tahtela --- src/corelib/io/qtldurl.cpp | 34 +++++++++++++++++----------------- src/corelib/io/qtldurl_p.h | 34 +++++++++++++++++----------------- src/gui/painting/qcosmeticstroker.cpp | 34 +++++++++++++++++----------------- src/gui/painting/qcosmeticstroker_p.h | 34 +++++++++++++++++----------------- 4 files changed, 68 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp index 7db4bbddd5..7d06ca4b17 100644 --- a/src/corelib/io/qtldurl.cpp +++ b/src/corelib/io/qtldurl.cpp @@ -7,29 +7,29 @@ ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** GNU Lesser General Public License Usage -** Alternatively, 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. +** 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 +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** ** ** diff --git a/src/corelib/io/qtldurl_p.h b/src/corelib/io/qtldurl_p.h index 152ffa0f63..77c0a15823 100644 --- a/src/corelib/io/qtldurl_p.h +++ b/src/corelib/io/qtldurl_p.h @@ -7,29 +7,29 @@ ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** GNU Lesser General Public License Usage -** Alternatively, 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. +** 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 +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** ** ** diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index cdc0978ed7..dbe957e68d 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -7,29 +7,29 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** GNU Lesser General Public License Usage -** Alternatively, 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. +** 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 +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** ** ** diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h index 0aa71fc9cd..d7bd79ad15 100644 --- a/src/gui/painting/qcosmeticstroker_p.h +++ b/src/gui/painting/qcosmeticstroker_p.h @@ -7,29 +7,29 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** GNU Lesser General Public License Usage -** Alternatively, 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. +** 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 +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** ** ** -- cgit v1.2.3 From fcca106e590ba550c536a6b8de1b011ccc2c0d30 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 6 Jul 2011 09:17:00 +0200 Subject: Add an internal QRefCount class to QtCore The class will be used by QString and possibly other container classes to allow for the Data objects to be created at compile time in read-only memory. Change-Id: I9c7538bc97df637cc920e6e5ef23d67a93abac0d Reviewed-on: http://codereview.qt.nokia.com/1216 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/tools/qrefcount.cpp | 51 +++++++++++++++++++++++ src/corelib/tools/qrefcount.h | 92 +++++++++++++++++++++++++++++++++++++++++ src/corelib/tools/tools.pri | 2 + 3 files changed, 145 insertions(+) create mode 100644 src/corelib/tools/qrefcount.cpp create mode 100644 src/corelib/tools/qrefcount.h (limited to 'src') diff --git a/src/corelib/tools/qrefcount.cpp b/src/corelib/tools/qrefcount.cpp new file mode 100644 index 0000000000..c40214b2ab --- /dev/null +++ b/src/corelib/tools/qrefcount.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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$ +** +****************************************************************************/ + +/*! + \class QtPrivate::RefCount + \internal + + QRefCount implements atomic ref counting for Qt's shared classes. It behaves very similar + to QAtomicInt, but ignores negative ref counts. + + This can be used to allow to implement e.g. const read-only QStringData objects. QString::shared_null and + the qs(...) macro make use of this feature. +*/ diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h new file mode 100644 index 0000000000..9223cfe352 --- /dev/null +++ b/src/corelib/tools/qrefcount.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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 QREFCOUNT_H +#define QREFCOUNT_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +namespace QtPrivate +{ + +class RefCount +{ +public: + inline void ref() { + if (atomic >= 0) + atomic.ref(); + } + + inline bool deref() { + if (atomic < 0) + return true; + return atomic.deref(); + } + + inline bool operator==(int value) const + { return atomic.operator ==(value); } + inline bool operator!=(int value) const + { return atomic.operator !=(value); } + inline bool operator!() const + { return atomic.operator !(); } + inline operator int() const + { return atomic.operator int(); } + inline RefCount &operator=(int value) + { atomic = value; return *this; } + + QBasicAtomicInt atomic; +}; + +#define Q_REFCOUNT_INITIALIZER(a) { Q_BASIC_ATOMIC_INITIALIZER(a) } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 42cab84cc0..f5b38eb1c0 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -30,6 +30,7 @@ HEADERS += \ tools/qrect.h \ tools/qregexp.h \ tools/qringbuffer_p.h \ + tools/qrefcount.h \ tools/qscopedpointer.h \ tools/qscopedpointer_p.h \ tools/qscopedvaluerollback.h \ @@ -72,6 +73,7 @@ SOURCES += \ tools/qcontiguouscache.cpp \ tools/qrect.cpp \ tools/qregexp.cpp \ + tools/qrefcount.cpp \ tools/qshareddata.cpp \ tools/qsharedpointer.cpp \ tools/qsimd.cpp \ -- cgit v1.2.3 From ee85e9cc10bc6874c892b09fa54b5dbd79854069 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 6 Jul 2011 09:21:10 +0200 Subject: Support for compile time generated QStrings use with QString string(QStringLiteral("foo")) or QString string(qs("foo")). qs(...) can in almost all places replace QLatin1String. the Macro qs requires c++0x support or a compiler where sizeof(wchar_t) == 2. In case these conditions are not met, qs simply falls back to QLatin1String. The commit also cleans up the QStringData structure significantly, now using only 16 bytes for the header on 32 bit systems. The bitflags to store unicode directionality of the string and whether the string would require complex text processing to render are removed. They don't really belong here and the result can be calculated very fast in any case. Added an internal QRefCount class the encapsulates the reference counting semantics required where a negative refcount is never changed. This is required to be able to put the string data into a constant POD object. Change-Id: I5b1395213deca48b2d582a036a0e8a8358d26d14 Reviewed-on: http://codereview.qt.nokia.com/1218 Reviewed-by: Olivier Goffart Reviewed-by: Lars Knoll --- src/corelib/tools/qstring.cpp | 439 +++++++++++++++++++----------------------- src/corelib/tools/qstring.h | 130 +++++++++---- 2 files changed, 287 insertions(+), 282 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index afb396ce50..eb5804b254 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -797,10 +797,8 @@ const QString::Null QString::null = { }; \sa split() */ -QString::Data QString::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), - 0, 0, shared_null.array, 0, 0, 0, 0, 0, {0} }; -QString::Data QString::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), - 0, 0, shared_empty.array, 0, 0, 0, 0, 0, {0} }; +const QConstStringData<1> QString::shared_null = (const QConstStringData<1>) { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } }; +const QConstStringData<1> QString::shared_empty = (const QConstStringData<1>) { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } }; int QString::grow(int size) { @@ -1044,20 +1042,15 @@ int QString::toWCharArray(wchar_t *array) const QString::QString(const QChar *unicode, int size) { if (!unicode) { - d = &shared_null; - d->ref.ref(); + d = const_cast(&shared_null.str); } else if (size <= 0) { - d = &shared_empty; - d->ref.ref(); + d = const_cast(&shared_empty.str); } else { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - memcpy(d->array, unicode, size * sizeof(QChar)); - d->array[size] = '\0'; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + memcpy(d->data(), unicode, size * sizeof(QChar)); + d->data()[size] = '\0'; } } @@ -1073,24 +1066,19 @@ QString::QString(const QChar *unicode, int size) QString::QString(const QChar *unicode) { if (!unicode) { - d = &shared_null; - d->ref.ref(); + d = const_cast(&shared_null.str); } else { int size = 0; while (unicode[size] != 0) ++size; if (!size) { - d = &shared_empty; - d->ref.ref(); + d = const_cast(&shared_empty.str); } else { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - memcpy(d->array, unicode, size * sizeof(QChar)); - d->array[size] = '\0'; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + memcpy(d->data(), unicode, size * sizeof(QChar)); + d->data()[size] = '\0'; } } } @@ -1105,18 +1093,14 @@ QString::QString(const QChar *unicode) QString::QString(int size, QChar ch) { if (size <= 0) { - d = &shared_empty; - d->ref.ref(); + d = const_cast(&shared_empty.str); } else { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[size] = '\0'; - ushort *i = d->array + size; - ushort *b = d->array; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + d->data()[size] = '\0'; + ushort *i = d->data() + size; + ushort *b = d->data(); const ushort value = ch.unicode(); while (i != b) *--i = value; @@ -1131,13 +1115,10 @@ QString::QString(int size, QChar ch) */ QString::QString(int size, Qt::Initialization) { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[size] = '\0'; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + d->data()[size] = '\0'; } /*! \fn QString::QString(const QLatin1String &str) @@ -1152,15 +1133,11 @@ QString::QString(int size, Qt::Initialization) */ QString::QString(QChar ch) { - void *buf = qMalloc(sizeof(Data) + sizeof(QChar)); - Q_CHECK_PTR(buf); - d = reinterpret_cast(buf); - d->ref = 1; - d->alloc = d->size = 1; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[0] = ch.unicode(); - d->array[1] = '\0'; + d = (Data *) qMalloc(sizeof(Data) + 2*sizeof(QChar)); + Q_CHECK_PTR(d); + *d = (Data) { Q_REFCOUNT_INITIALIZER(1), 1, 1, false, { 0 } }; + d->data()[0] = ch.unicode(); + d->data()[1] = '\0'; } /*! \fn QString::QString(const QByteArray &ba) @@ -1256,21 +1233,23 @@ void QString::resize(int size) if (size < 0) size = 0; - if (size == 0 && !d->capacity) { - Data *x = &shared_empty; - x->ref.ref(); + if (d->offset && d->ref == 1 && size < d->size) { + d->size = size; + return; + } + + if (size == 0 && !d->capacityReserved) { + Data *x = const_cast(&shared_empty.str); if (!d->ref.deref()) QString::free(d); d = x; } else { if (d->ref != 1 || size > d->alloc || - (!d->capacity && size < d->size && size < d->alloc >> 1)) + (!d->capacityReserved && size < d->size && size < d->alloc >> 1)) realloc(grow(size)); if (d->alloc >= size) { d->size = size; - if (d->data == d->array) { - d->array[size] = '\0'; - } + d->data()[size] = '\0'; } } } @@ -1328,28 +1307,21 @@ void QString::resize(int size) // ### Qt 5: rename reallocData() to avoid confusion. 197625 void QString::realloc(int alloc) { - if (d->ref != 1 || d->data != d->array) { - Data *x = static_cast(qMalloc(sizeof(Data) + alloc * sizeof(QChar))); + if (d->ref != 1 || d->offset) { + Data *x = static_cast(qMalloc(sizeof(Data) + (alloc+1) * sizeof(QChar))); Q_CHECK_PTR(x); - x->size = qMin(alloc, d->size); - ::memcpy(x->array, d->data, x->size * sizeof(QChar)); - x->array[x->size] = 0; - x->ref = 1; - x->alloc = alloc; - x->clean = d->clean; - x->simpletext = d->simpletext; - x->righttoleft = d->righttoleft; - x->capacity = d->capacity; - x->data = x->array; + *x = (Data){ Q_REFCOUNT_INITIALIZER(1), qMin(alloc, d->size), alloc, d->capacityReserved, { 0 } }; + ::memcpy(x->data(), d->data(), x->size * sizeof(QChar)); + x->data()[x->size] = 0; if (!d->ref.deref()) QString::free(d); d = x; } else { - Data *p = static_cast(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Data *p = static_cast(qRealloc(d, sizeof(Data) + (alloc+1) * sizeof(QChar))); Q_CHECK_PTR(p); d = p; d->alloc = alloc; - d->data = d->array; + d->offset = 0; } } @@ -1363,8 +1335,8 @@ void QString::expand(int i) int sz = d->size; resize(qMax(i + 1, sz)); if (d->size - 1 > sz) { - ushort *n = d->data + d->size - 1; - ushort *e = d->data + sz; + ushort *n = d->data() + d->size - 1; + ushort *e = d->data() + sz; while (n != e) * --n = ' '; } @@ -1482,9 +1454,9 @@ QString &QString::insert(int i, const QLatin1String &str) int len = qstrlen(str.latin1()); expand(qMax(d->size, i) + len - 1); - ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar)); + ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar)); for (int j = 0; j < len; ++j) - d->data[i + j] = s[j]; + d->data()[i + j] = s[j]; return *this; } @@ -1501,7 +1473,7 @@ QString& QString::insert(int i, const QChar *unicode, int size) return *this; const ushort *s = (const ushort *)unicode; - if (s >= d->data && s < d->data + d->alloc) { + if (s >= d->data() && s < d->data() + d->alloc) { // Part of me - take a copy ushort *tmp = static_cast(qMalloc(size * sizeof(QChar))); Q_CHECK_PTR(tmp); @@ -1513,8 +1485,8 @@ QString& QString::insert(int i, const QChar *unicode, int size) expand(qMax(d->size, i) + size - 1); - ::memmove(d->data + i + size, d->data + i, (d->size - i - size) * sizeof(QChar)); - memcpy(d->data + i, s, size * sizeof(QChar)); + ::memmove(d->data() + i + size, d->data() + i, (d->size - i - size) * sizeof(QChar)); + memcpy(d->data() + i, s, size * sizeof(QChar)); return *this; } @@ -1532,8 +1504,8 @@ QString& QString::insert(int i, QChar ch) if (i < 0) return *this; expand(qMax(i, d->size)); - ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar)); - d->data[i] = ch.unicode(); + ::memmove(d->data() + i + 1, d->data() + i, (d->size - i) * sizeof(QChar)); + d->data()[i] = ch.unicode(); return *this; } @@ -1557,15 +1529,15 @@ QString& QString::insert(int i, QChar ch) */ QString &QString::append(const QString &str) { - if (str.d != &shared_null) { - if (d == &shared_null) { + if (str.d != &shared_null.str) { + if (d == &shared_null.str) { operator=(str); } else { if (d->ref != 1 || d->size + str.d->size > d->alloc) realloc(grow(d->size + str.d->size)); - memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar)); + memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar)); d->size += str.d->size; - d->data[d->size] = '\0'; + d->data()[d->size] = '\0'; } } return *this; @@ -1583,7 +1555,7 @@ QString &QString::append(const QLatin1String &str) int len = qstrlen((char *)s); if (d->ref != 1 || d->size + len > d->alloc) realloc(grow(d->size + len)); - ushort *i = d->data + d->size; + ushort *i = d->data() + d->size; while ((*i++ = *s++)) ; d->size += len; @@ -1626,8 +1598,8 @@ QString &QString::append(QChar ch) { if (d->ref != 1 || d->size + 1 > d->alloc) realloc(grow(d->size + 1)); - d->data[d->size++] = ch.unicode(); - d->data[d->size] = '\0'; + d->data()[d->size++] = ch.unicode(); + d->data()[d->size] = '\0'; return *this; } @@ -1707,7 +1679,7 @@ QString &QString::remove(int pos, int len) resize(pos); // truncate } else if (len > 0) { detach(); - memmove(d->data + pos, d->data + pos + len, + memmove(d->data() + pos, d->data() + pos + len, (d->size - pos - len + 1) * sizeof(ushort)); d->size -= len; } @@ -1756,14 +1728,14 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs) ushort c = ch.unicode(); if (cs == Qt::CaseSensitive) { while (i < d->size) - if (d->data[i] == ch) + if (d->data()[i] == ch) remove(i, 1); else i++; } else { c = foldCase(c); while (i < d->size) - if (foldCase(d->data[i]) == c) + if (foldCase(d->data()[i]) == c) remove(i, 1); else i++; @@ -1859,10 +1831,10 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS */ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen) { - // copy *after in case it lies inside our own d->data area + // copy *after in case it lies inside our own d->data() area // (which we could possibly invalidate via a realloc or corrupt via memcpy operations.) QChar *afterBuffer = const_cast(after); - if (after >= reinterpret_cast(d->data) && after < reinterpret_cast(d->data) + d->size) { + if (after >= reinterpret_cast(d->data()) && after < reinterpret_cast(d->data()) + d->size) { afterBuffer = static_cast(qMalloc(alen*sizeof(QChar))); Q_CHECK_PTR(afterBuffer); ::memcpy(afterBuffer, after, alen*sizeof(QChar)); @@ -1873,30 +1845,30 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar // replace in place detach(); for (int i = 0; i < nIndices; ++i) - memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar)); + memcpy(d->data() + indices[i], afterBuffer, alen * sizeof(QChar)); } else if (alen < blen) { // replace from front detach(); uint to = indices[0]; if (alen) - memcpy(d->data+to, after, alen*sizeof(QChar)); + memcpy(d->data()+to, after, alen*sizeof(QChar)); to += alen; uint movestart = indices[0] + blen; for (int i = 1; i < nIndices; ++i) { int msize = indices[i] - movestart; if (msize > 0) { - memmove(d->data + to, d->data + movestart, msize * sizeof(QChar)); + memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar)); to += msize; } if (alen) { - memcpy(d->data + to, afterBuffer, alen*sizeof(QChar)); + memcpy(d->data() + to, afterBuffer, alen*sizeof(QChar)); to += alen; } movestart = indices[i] + blen; } int msize = d->size - movestart; if (msize > 0) - memmove(d->data + to, d->data + movestart, msize * sizeof(QChar)); + memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar)); resize(d->size - nIndices*(blen-alen)); } else { // replace from back @@ -1910,9 +1882,9 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar int movestart = indices[nIndices] + blen; int insertstart = indices[nIndices] + nIndices*(alen-blen); int moveto = insertstart + alen; - memmove(d->data + moveto, d->data + movestart, + memmove(d->data() + moveto, d->data() + movestart, (moveend - movestart)*sizeof(QChar)); - memcpy(d->data + insertstart, afterBuffer, alen*sizeof(QChar)); + memcpy(d->data() + insertstart, afterBuffer, alen*sizeof(QChar)); moveend = movestart-blen; } } @@ -1994,7 +1966,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs return remove(ch, cs); if (after.d->size == 1) - return replace(ch, after.d->data[0], cs); + return replace(ch, after.d->data()[0], cs); if (d->size == 0) return *this; @@ -2007,13 +1979,13 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs uint pos = 0; if (cs == Qt::CaseSensitive) { while (pos < 1023 && index < d->size) { - if (d->data[index] == cc) + if (d->data()[index] == cc) indices[pos++] = index; index++; } } else { while (pos < 1023 && index < d->size) { - if (QChar::toCaseFolded(d->data[index]) == cc) + if (QChar::toCaseFolded(d->data()[index]) == cc) indices[pos++] = index; index++; } @@ -2045,7 +2017,7 @@ QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs) ushort b = before.unicode(); if (d->size) { detach(); - ushort *i = d->data; + ushort *i = d->data(); const ushort *e = i + d->size; if (cs == Qt::CaseSensitive) { for (; i != e; ++i) @@ -2170,7 +2142,7 @@ bool QString::operator==(const QString &other) const if (d->size != other.d->size) return false; - return qMemEquals(d->data, other.d->data, d->size); + return qMemEquals(d->data(), other.d->data(), d->size); } /*! @@ -2178,7 +2150,7 @@ bool QString::operator==(const QString &other) const */ bool QString::operator==(const QLatin1String &other) const { - const ushort *uc = d->data; + const ushort *uc = d->data(); const ushort *e = uc + d->size; const uchar *c = (uchar *)other.latin1(); @@ -2240,7 +2212,7 @@ bool QString::operator<(const QString &other) const */ bool QString::operator<(const QLatin1String &other) const { - const ushort *uc = d->data; + const ushort *uc = d->data(); const ushort *e = uc + d->size; const uchar *c = (uchar *) other.latin1(); @@ -2342,7 +2314,7 @@ bool QString::operator<(const QLatin1String &other) const */ bool QString::operator>(const QLatin1String &other) const { - const ushort *uc = d->data;; + const ushort *uc = d->data();; const ushort *e = uc + d->size; const uchar *c = (uchar *) other.latin1(); @@ -2687,7 +2659,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c { const int sl = str.d->size; if (sl == 1) - return lastIndexOf(QChar(str.d->data[0]), from, cs); + return lastIndexOf(QChar(str.d->data()[0]), from, cs); const int l = d->size; if (from < 0) @@ -2700,7 +2672,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs); + return lastIndexOfHelper(d->data(), from, str.d->data(), str.d->size, cs); } /*! @@ -2743,7 +2715,7 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity for (int i = 0; i < sl; ++i) s[i] = str.latin1()[i]; - return lastIndexOfHelper(d->data, from, s.data(), sl, cs); + return lastIndexOfHelper(d->data(), from, s.data(), sl, cs); } /*! @@ -2789,7 +2761,7 @@ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, reinterpret_cast(str.unicode()), + return lastIndexOfHelper(d->data(), from, reinterpret_cast(str.unicode()), str.size(), cs); } @@ -2940,14 +2912,14 @@ QString& QString::replace(const QRegExp &rx, const QString &after) while (i < pos) { int copyend = replacements[i].pos; int size = copyend - copystart; - memcpy(uc, d->data + copystart, size * sizeof(QChar)); + memcpy(uc, d->data() + copystart, size * sizeof(QChar)); uc += size; - memcpy(uc, after.d->data, al * sizeof(QChar)); + memcpy(uc, after.d->data(), al * sizeof(QChar)); uc += al; copystart = copyend + replacements[i].length; i++; } - memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar)); + memcpy(uc, d->data() + copystart, (d->size - copystart) * sizeof(QChar)); newstring.resize(newlen); *this = newstring; caretMode = QRegExp::CaretWontMatch; @@ -3366,7 +3338,7 @@ QString QString::left(int n) const { if (n >= d->size || n < 0) return *this; - return QString((const QChar*) d->data, n); + return QString((const QChar*) d->data(), n); } /*! @@ -3384,7 +3356,7 @@ QString QString::right(int n) const { if (n >= d->size || n < 0) return *this; - return QString((const QChar*) d->data + d->size - n, n); + return QString((const QChar*) d->data() + d->size - n, n); } /*! @@ -3406,7 +3378,7 @@ QString QString::right(int n) const QString QString::mid(int position, int n) const { - if (d == &shared_null || position >= d->size) + if (d == &shared_null.str || position >= d->size) return QString(); if (n < 0) n = d->size - position; @@ -3418,7 +3390,7 @@ QString QString::mid(int position, int n) const n = d->size - position; if (position == 0 && n == d->size) return *this; - return QString((const QChar*) d->data + position, n); + return QString((const QChar*) d->data() + position, n); } /*! @@ -3456,8 +3428,8 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const { return d->size && (cs == Qt::CaseSensitive - ? d->data[0] == c - : foldCase(d->data[0]) == foldCase(c.unicode())); + ? d->data()[0] == c + : foldCase(d->data()[0]) == foldCase(c.unicode())); } /*! @@ -3530,8 +3502,8 @@ bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const { return d->size && (cs == Qt::CaseSensitive - ? d->data[d->size - 1] == c - : foldCase(d->data[d->size - 1]) == foldCase(c.unicode())); + ? d->data()[d->size - 1] == c + : foldCase(d->data()[d->size - 1]) == foldCase(c.unicode())); } /*! \fn const char *QString::ascii() const @@ -3765,22 +3737,17 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size) { Data *d; if (!str) { - d = &shared_null; - d->ref.ref(); + d = const_cast(&shared_null.str); } else if (size == 0 || (!*str && size < 0)) { - d = &shared_empty; - d->ref.ref(); + d = const_cast(&shared_empty.str); } else { if (size < 0) size = qstrlen(str); - d = static_cast(qMalloc(sizeof(Data) + size * sizeof(QChar))); + d = static_cast(qMalloc(sizeof(Data) + (size+1) * sizeof(QChar))); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[size] = '\0'; - ushort *dst = d->data; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + d->data()[size] = '\0'; + ushort *dst = d->data(); /* SIMD: * Unpacking with SSE has been shown to improve performance on recent CPUs * The same method gives no improvement with NEON. @@ -3818,11 +3785,9 @@ QString::Data *QString::fromAscii_helper(const char *str, int size) if (codecForCStrings) { Data *d; if (!str) { - d = &shared_null; - d->ref.ref(); + d = const_cast(&shared_null.str); } else if (size == 0 || (!*str && size < 0)) { - d = &shared_empty; - d->ref.ref(); + d = const_cast(&shared_empty.str); } else { if (size < 0) size = qstrlen(str); @@ -3995,7 +3960,7 @@ QString& QString::setUnicode(const QChar *unicode, int size) { resize(size); if (unicode && size) - memcpy(d->data, unicode, size * sizeof(QChar)); + memcpy(d->data(), unicode, size * sizeof(QChar)); return *this; } @@ -4034,7 +3999,7 @@ QString QString::simplified() const if (d->size == 0) return *this; - const QChar * const start = reinterpret_cast(d->data); + const QChar * const start = reinterpret_cast(d->data()); const QChar *from = start; const QChar *fromEnd = start + d->size; forever { @@ -4043,8 +4008,7 @@ QString QString::simplified() const break; if (++from == fromEnd) { // All-whitespace string - shared_empty.ref.ref(); - return QString(&shared_empty, 0); + return QString(shared_empty); } } // This loop needs no underflow check, as we already determined that @@ -4079,7 +4043,7 @@ QString QString::simplified() const // of already simplified characters - at least one, obviously - // without a trailing space. QString result((fromEnd - from) + copyCount, Qt::Uninitialized); - QChar *to = reinterpret_cast(result.d->data); + QChar *to = reinterpret_cast(result.d->data()); ::memcpy(to, copyFrom, copyCount * 2); to += copyCount; fromEnd--; @@ -4100,7 +4064,7 @@ QString QString::simplified() const } done: *to++ = ch; - result.truncate(to - reinterpret_cast(result.d->data)); + result.truncate(to - reinterpret_cast(result.d->data())); return result; } @@ -4124,7 +4088,7 @@ QString QString::trimmed() const { if (d->size == 0) return *this; - const QChar *s = (const QChar*)d->data; + const QChar *s = (const QChar*)d->data(); if (!s->isSpace() && !s[d->size-1].isSpace()) return *this; int start = 0; @@ -4137,8 +4101,7 @@ QString QString::trimmed() const } int l = end - start + 1; if (l <= 0) { - shared_empty.ref.ref(); - return QString(&shared_empty, 0); + return QString(shared_empty); } return QString(s + start, l); } @@ -4250,8 +4213,8 @@ QString& QString::fill(QChar ch, int size) { resize(size < 0 ? d->size : size); if (d->size) { - QChar *i = (QChar*)d->data + d->size; - QChar *b = (QChar*)d->data; + QChar *i = (QChar*)d->data() + d->size; + QChar *b = (QChar*)d->data(); while (i != b) *--i = ch; } @@ -4597,7 +4560,7 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const { if (cs == Qt::CaseSensitive) return ucstrcmp(constData(), length(), other.constData(), other.length()); - return ucstricmp(d->data, d->data + d->size, other.d->data, other.d->data + other.d->size); + return ucstricmp(d->data(), d->data() + d->size, other.d->data(), other.d->data() + other.d->size); } /*! @@ -4828,12 +4791,9 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, const ushort *QString::utf16() const { - if (d->data != d->array) { - QString *that = const_cast(this); - that->realloc(); // ensure '\\0'-termination for ::fromRawData strings - return that->d->data; - } - return d->array; + if (d->offset) + const_cast(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings + return d->data(); } /*! @@ -4862,8 +4822,8 @@ QString QString::leftJustified(int width, QChar fill, bool truncate) const if (padlen > 0) { result.resize(len+padlen); if (len) - memcpy(result.d->data, d->data, sizeof(QChar)*len); - QChar *uc = (QChar*)result.d->data + len; + memcpy(result.d->data(), d->data(), sizeof(QChar)*len); + QChar *uc = (QChar*)result.d->data() + len; while (padlen--) * uc++ = fill; } else { @@ -4900,11 +4860,11 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const int padlen = width - len; if (padlen > 0) { result.resize(len+padlen); - QChar *uc = (QChar*)result.d->data; + QChar *uc = (QChar*)result.d->data(); while (padlen--) * uc++ = fill; if (len) - memcpy(uc, d->data, sizeof(QChar)*len); + memcpy(uc, d->data(), sizeof(QChar)*len); } else { if (truncate) result = left(width); @@ -4924,7 +4884,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const QString QString::toLower() const { - const ushort *p = d->data; + const ushort *p = d->data(); if (!p) return *this; if (!d->size) @@ -4939,7 +4899,7 @@ QString QString::toLower() const } #endif - const ushort *e = d->data + d->size; + const ushort *e = d->data() + d->size; // this avoids one out of bounds check in the loop if (QChar(*p).isLowSurrogate()) @@ -4952,17 +4912,17 @@ QString QString::toLower() const const QUnicodeTables::Properties *prop = qGetProp(c); if (prop->lowerCaseDiff || prop->lowerCaseSpecial) { QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort)); - ushort *pp = s.d->data + (p - d->data); + memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); + ushort *pp = s.d->data() + (p - d->data()); while (p < e) { uint c = *p; if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) c = QChar::surrogateToUcs4(*(p - 1), c); prop = qGetProp(c); if (prop->lowerCaseSpecial) { - int pos = pp - s.d->data; + int pos = pp - s.d->data(); s.resize(s.d->size + SPECIAL_CASE_MAX_LEN); - pp = s.d->data + pos; + pp = s.d->data() + pos; const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff; while (*specialCase) *pp++ = *specialCase++; @@ -4971,7 +4931,7 @@ QString QString::toLower() const } ++p; } - s.truncate(pp - s.d->data); + s.truncate(pp - s.d->data()); return s; } ++p; @@ -4988,11 +4948,11 @@ QString QString::toCaseFolded() const if (!d->size) return *this; - const ushort *p = d->data; + const ushort *p = d->data(); if (!p) return *this; - const ushort *e = d->data + d->size; + const ushort *e = d->data() + d->size; uint last = 0; while (p < e) { @@ -5000,9 +4960,9 @@ QString QString::toCaseFolded() const if (folded != *p) { QString s(*this); s.detach(); - ushort *pp = s.d->data + (p - d->data); - const ushort *ppe = s.d->data + s.d->size; - last = pp > s.d->data ? *(pp - 1) : 0; + ushort *pp = s.d->data() + (p - d->data()); + const ushort *ppe = s.d->data() + s.d->size; + last = pp > s.d->data() ? *(pp - 1) : 0; while (pp < ppe) { *pp = foldCase(*pp, last); ++pp; @@ -5024,7 +4984,7 @@ QString QString::toCaseFolded() const QString QString::toUpper() const { - const ushort *p = d->data; + const ushort *p = d->data(); if (!p) return *this; if (!d->size) @@ -5039,7 +4999,7 @@ QString QString::toUpper() const } #endif - const ushort *e = d->data + d->size; + const ushort *e = d->data() + d->size; // this avoids one out of bounds check in the loop if (QChar(*p).isLowSurrogate()) @@ -5052,17 +5012,17 @@ QString QString::toUpper() const const QUnicodeTables::Properties *prop = qGetProp(c); if (prop->upperCaseDiff || prop->upperCaseSpecial) { QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort)); - ushort *pp = s.d->data + (p - d->data); + memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); + ushort *pp = s.d->data() + (p - d->data()); while (p < e) { uint c = *p; if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) c = QChar::surrogateToUcs4(*(p - 1), c); prop = qGetProp(c); if (prop->upperCaseSpecial) { - int pos = pp - s.d->data; + int pos = pp - s.d->data(); s.resize(s.d->size + SPECIAL_CASE_MAX_LEN); - pp = s.d->data + pos; + pp = s.d->data() + pos; const ushort *specialCase = specialCaseMap + prop->upperCaseDiff; while (*specialCase) *pp++ = *specialCase++; @@ -5071,7 +5031,7 @@ QString QString::toUpper() const } ++p; } - s.truncate(pp - s.d->data); + s.truncate(pp - s.d->data()); return s; } ++p; @@ -6196,19 +6156,19 @@ QString QString::repeated(int times) const if (result.d->alloc != resultSize) return QString(); // not enough memory - memcpy(result.d->data, d->data, d->size * sizeof(ushort)); + memcpy(result.d->data(), d->data(), d->size * sizeof(ushort)); int sizeSoFar = d->size; - ushort *end = result.d->data + sizeSoFar; + ushort *end = result.d->data() + sizeSoFar; const int halfResultSize = resultSize >> 1; while (sizeSoFar <= halfResultSize) { - memcpy(end, result.d->data, sizeSoFar * sizeof(ushort)); + memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort)); end += sizeSoFar; sizeSoFar <<= 1; } - memcpy(end, result.d->data, (resultSize - sizeSoFar) * sizeof(ushort)); - result.d->data[resultSize] = '\0'; + memcpy(end, result.d->data(), (resultSize - sizeSoFar) * sizeof(ushort)); + result.d->data()[resultSize] = '\0'; result.d->size = resultSize; return result; } @@ -6902,7 +6862,7 @@ QString QString::multiArg(int numArgs, const QString **args) const { QString result; QMap numbersUsed; - const QChar *uc = (const QChar *) d->data; + const QChar *uc = (const QChar *) d->data(); const int len = d->size; const int end = len - 1; int lastNumber = -1; @@ -6951,62 +6911,50 @@ QString QString::multiArg(int numArgs, const QString **args) const return result; } -static bool isStringRightToLeft(const ushort *p, const ushort *end) -{ - bool righttoleft = false; - while (p < end) { - switch(QChar::direction(*p)) - { - case QChar::DirL: - goto end; - case QChar::DirR: - case QChar::DirAL: - righttoleft = true; - goto end; - default: - break; - } - ++p; - } - end: - return righttoleft; -} -/*! \internal - */ -void QString::updateProperties() const +/*! \fn bool QString::isSimpleText() const + + \internal +*/ +bool QString::isSimpleText() const { - ushort *p = d->data; - ushort *end = p + d->size; - d->simpletext = true; + const ushort *p = d->data(); + const ushort * const end = p + d->size; while (p < end) { ushort uc = *p; // sort out regions of complex text formatting if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) { - d->simpletext = false; + return false; } p++; } - d->righttoleft = isStringRightToLeft(d->data, d->data + d->size); - d->clean = true; -} - -bool QString::isRightToLeft() const -{ - return isStringRightToLeft(d->data, d->data + d->size); + return true; } -/*! \fn bool QString::isSimpleText() const - - \internal -*/ - /*! \fn bool QString::isRightToLeft() const Returns true if the string is read right to left. */ - +bool QString::isRightToLeft() const +{ + const ushort *p = d->data(); + const ushort * const end = p + d->size; + while (p < end) { + switch(QChar::direction(*p)) + { + case QChar::DirL: + return false; + case QChar::DirR: + case QChar::DirAL: + return true; + default: + break; + } + ++p; + } + return false; +} /*! \fn QChar *QString::data() @@ -7122,17 +7070,13 @@ bool QString::isRightToLeft() const QString QString::fromRawData(const QChar *unicode, int size) { Data *x = static_cast(qMalloc(sizeof(Data))); + *x = (Data){ Q_REFCOUNT_INITIALIZER(1), size, 0, false, { 0 } }; Q_CHECK_PTR(x); if (unicode) { - x->data = (ushort *)unicode; + x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort)); } else { - x->data = x->array; size = 0; } - x->ref = 1; - x->alloc = x->size = size; - *x->array = '\0'; - x->clean = x->simpletext = x->righttoleft = x->capacity = 0; return QString(x, 0); } @@ -7152,18 +7096,16 @@ QString QString::fromRawData(const QChar *unicode, int size) */ QString &QString::setRawData(const QChar *unicode, int size) { - if (d->ref != 1 || (d->data == d->array && d->alloc)) { + if (d->ref != 1 || d->alloc) { *this = fromRawData(unicode, size); } else { if (unicode) { - d->data = (ushort *)unicode; + d->size = size; + d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort)); } else { - d->data = d->array; - size = 0; + d->offset = 0; + d->size = 0; } - d->alloc = d->size = size; - *d->array = '\0'; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; } return *this; } @@ -7212,7 +7154,7 @@ QString &QString::setRawData(const QChar *unicode, int size) \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 6 - \sa QString, QLatin1Char + \sa QString, QLatin1Char, QStringLiteral */ /*! \fn QLatin1String::QLatin1String(const char *str) @@ -8345,7 +8287,7 @@ QStringRef QString::rightRef(int n) const QStringRef QString::midRef(int position, int n) const { - if (d == &shared_null || position >= d->size) + if (d == &shared_null.str || position >= d->size) return QStringRef(); if (n < 0) n = d->size - position; @@ -9071,4 +9013,21 @@ QVector QStringRef::toUcs4() const return v; } +/*! + \macro QStringLiteral(str) + \relates QString + + The macro generates the data for a QString out of \a str at compile time if the compiler supports it. + Creating a QString from it is free in this case, and the generated string data is stored in + the read-only segment of the compiled object file. + + Using QStringLiteral instead of a double quoted ascii literal can significantly speed up creation + of QString's from data known at compile time. + + If the compiler is c++0x enabled the string \a str can actually contain unicode data. + + For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to + QLatin1String. +*/ + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 154012d132..81dff3d309 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -44,7 +44,7 @@ #include #include -#include +#include #include #ifndef QT_NO_STL @@ -77,9 +77,65 @@ class QLatin1String; class QStringRef; template class QVector; +struct QStringData { + QtPrivate::RefCount ref; + 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; } +}; + + +#if defined(Q_COMPILER_UNICODE_STRINGS) + +template struct QConstStringData +{ + const QStringData str; + const char16_t data[n]; + operator const QStringData &() const { return str; } +}; +#define QStringLiteral(str) (const QConstStringData) \ +{ { Q_REFCOUNT_INITIALIZER(-1), sizeof(u"" str)/2 -1, 0, 0, { 0 } }, u"" str } + +// wchar_t is 2 bytes +#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) + +template struct QConstStringData +{ + const QStringData str; + const wchar_t data[n]; + operator const QStringData &() const { return str; } +}; +#define QStringLiteral(str) (const QConstStringData) \ +{ { Q_REFCOUNT_INITIALIZER(-1), sizeof(L"" str)/2 -1, 0, 0, { 0 } }, L"" str } + +// fallback, uses QLatin1String as next best options +#else + +template struct QConstStringData +{ + const QStringData str; + const ushort data[n]; + operator const QStringData &() const { return str; } +}; +#define QStringLiteral(str) QLatin1String(str) + +#endif + +#ifndef QT_NO_KEYWORDS +#define qs(str) QStringLiteral(str) +#endif + class Q_CORE_EXPORT QString { 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 @@ -108,7 +164,7 @@ public: int capacity() const; inline void reserve(int size); - inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacity = 0;} + inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;} inline const QChar *unicode() const; inline QChar *data(); @@ -262,8 +318,8 @@ public: inline QString &operator+=(QChar c) { if (d->ref != 1 || d->size + 1 > d->alloc) realloc(grow(d->size + 1)); - d->data[d->size++] = c.unicode(); - d->data[d->size] = '\0'; + d->data()[d->size++] = c.unicode(); + d->data()[d->size] = '\0'; return *this; } @@ -491,15 +547,17 @@ public: // compatibility struct Null { }; static const Null null; - inline QString(const Null &): d(&shared_null) { d->ref.ref(); } + inline QString(const Null &): d(const_cast(&shared_null.str)) {} inline QString &operator=(const Null &) { *this = QString(); return *this; } - inline bool isNull() const { return d == &shared_null; } + inline bool isNull() const { return d == &shared_null.str; } - bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; } + bool isSimpleText() const; bool isRightToLeft() const; QString(int size, Qt::Initialization); + template + inline QString(const QConstStringData &dd) : d(const_cast(&dd.str)) {} private: #if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) @@ -511,22 +569,11 @@ private: QString &operator=(const QByteArray &a); #endif - struct Data { - QBasicAtomicInt ref; - int alloc, size; - ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then - ushort clean : 1; - ushort simpletext : 1; - ushort righttoleft : 1; - ushort capacity : 1; - ushort reserved : 11; - // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit - ushort array[1]; - }; - static Data shared_null; - static Data shared_empty; + static const QConstStringData<1> shared_null; + static const QConstStringData<1> shared_empty; Data *d; - QString(Data *dd, int /*dummy*/) : d(dd) {} + inline QString(Data *dd, int /*dummy*/) : d(dd) {} + #ifndef QT_NO_TEXTCODEC static QTextCodec *codecForCStrings; #endif @@ -605,23 +652,23 @@ inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLat inline int QString::length() const { return d->size; } inline const QChar QString::at(int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } inline const QChar QString::operator[](int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } inline const QChar QString::operator[](uint i) const -{ Q_ASSERT(i < uint(size())); return d->data[i]; } +{ Q_ASSERT(i < uint(size())); return d->data()[i]; } inline bool QString::isEmpty() const { return d->size == 0; } inline const QChar *QString::unicode() const -{ return reinterpret_cast(d->data); } +{ return reinterpret_cast(d->data()); } inline const QChar *QString::data() const -{ return reinterpret_cast(d->data); } +{ return reinterpret_cast(d->data()); } inline QChar *QString::data() -{ detach(); return reinterpret_cast(d->data); } +{ detach(); return reinterpret_cast(d->data()); } inline const QChar *QString::constData() const -{ return reinterpret_cast(d->data); } +{ return reinterpret_cast(d->data()); } inline void QString::detach() -{ if (d->ref != 1 || d->data != d->array) realloc(); } +{ if (d->ref != 1 || d->offset) realloc(); } inline bool QString::isDetached() const { return d->ref == 1; } inline QString &QString::operator=(const QLatin1String &s) @@ -703,10 +750,10 @@ public: // all this is not documented: We just say "like QChar" and let it be. inline operator QChar() const - { return i < s.d->size ? s.d->data[i] : 0; } + { return i < s.d->size ? s.d->data()[i] : 0; } inline QCharRef &operator=(const QChar &c) { if (i >= s.d->size) s.expand(i); else s.detach(); - s.d->data[i] = c.unicode(); return *this; } + s.d->data()[i] = c.unicode(); return *this; } // An operator= for each QChar cast constructors #ifndef QT_NO_CAST_FROM_ASCII @@ -773,9 +820,9 @@ inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); } inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); } -inline QString::QString() : d(&shared_null) { d->ref.ref(); } +inline QString::QString() : d(const_cast(&shared_null.str)) {} inline QString::~QString() { if (!d->ref.deref()) free(d); } -inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;} +inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true;} inline QString &QString::setUtf16(const ushort *autf16, int asize) { return setUnicode(reinterpret_cast(autf16), asize); } inline QCharRef QString::operator[](int i) @@ -783,17 +830,17 @@ inline QCharRef QString::operator[](int i) inline QCharRef QString::operator[](uint i) { return QCharRef(*this, i); } inline QString::iterator QString::begin() -{ detach(); return reinterpret_cast(d->data); } +{ detach(); return reinterpret_cast(d->data()); } inline QString::const_iterator QString::begin() const -{ return reinterpret_cast(d->data); } +{ return reinterpret_cast(d->data()); } inline QString::const_iterator QString::constBegin() const -{ return reinterpret_cast(d->data); } +{ return reinterpret_cast(d->data()); } inline QString::iterator QString::end() -{ detach(); return reinterpret_cast(d->data + d->size); } +{ detach(); return reinterpret_cast(d->data() + d->size); } inline QString::const_iterator QString::end() const -{ return reinterpret_cast(d->data + d->size); } +{ return reinterpret_cast(d->data() + d->size); } inline QString::const_iterator QString::constEnd() const -{ return reinterpret_cast(d->data + d->size); } +{ return reinterpret_cast(d->data() + d->size); } inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return QBool(indexOf(s, 0, cs) != -1); } inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const @@ -1024,7 +1071,7 @@ public: inline const QChar *unicode() const { if (!m_string) - return reinterpret_cast(QString::shared_null.data); + return reinterpret_cast(QString::shared_null.str.data()); return m_string->unicode() + m_position; } inline const QChar *data() const { return unicode(); } @@ -1154,7 +1201,6 @@ inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) c { return QBool(indexOf(s, 0, cs) != -1); } - QT_END_NAMESPACE QT_END_HEADER -- cgit v1.2.3 From f4c07fe72168778cd6ea5a6c07fb6add91b2e3d0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 4 Jul 2011 12:21:06 +0200 Subject: Unify QLatin1String and QLatin1Literal Unify the two classes and get rid of one TODO item for Qt 5. Using strlen in the constructor of QLatin1String works, as the compiler can do the calculation at compile time. Change-Id: I59d98c71a34b86d4211fa0d8cfd40b7d612c5a78 Reviewed-on: http://codereview.qt.nokia.com/1219 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/tools/qstring.cpp | 80 +++++++++++++++++++----------------- src/corelib/tools/qstring.h | 13 +++--- src/corelib/tools/qstringbuilder.cpp | 49 ++-------------------- src/corelib/tools/qstringbuilder.h | 38 +---------------- 4 files changed, 57 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index eb5804b254..fe6cae25d1 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -720,6 +720,18 @@ const QString::Null QString::null = { }; \section1 More Efficient String Construction + Many strings are known at compile time. But the trivial + constructor QString("Hello"), will convert the string literal + to a QString using the codecForCStrings(). To avoid this one + can use the QStringLiteral macro to directly create the required + data at compile time. Constructing a QString out of the literal + does then not cause any overhead at runtime. + + A slightly less efficient way is to use QLatin1String. This class wraps + a C string literal, precalculates it length at compile time and can + then be used for faster comparison with QStrings and conversion to + QStrings than a regular C string literal. + Using the QString \c{'+'} operator, it is easy to construct a complex string from multiple substrings. You will often write code like this: @@ -735,9 +747,6 @@ const QString::Null QString::null = { }; where \e{n > 2}, there can be as many as \e{n - 1} calls to the memory allocator. - Second, QLatin1String does not store its length internally but - calls qstrlen() when it needs to know its length. - In 4.6, an internal template class \c{QStringBuilder} has been added along with a few helper functions. This class is marked internal and does not appear in the documentation, because you @@ -755,12 +764,6 @@ const QString::Null QString::null = { }; then called \e{once} to get the required space, and the substrings are copied into it one by one. - \c{QLatin1Literal} is a second internal class that can replace - QLatin1String, which can't be changed for compatibility reasons. - \c{QLatin1Literal} stores its length, thereby saving time when - \c{QStringBuilder} computes the amount of memory required for the - final string. - Additional efficiency is gained by inlining and reduced reference counting (the QString created from a \c{QStringBuilder} typically has a ref count of 1, whereas QString::append() needs an extra @@ -2076,7 +2079,7 @@ QString &QString::replace(const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs) { - int blen = qstrlen(before.latin1()); + int blen = before.size(); QVarLengthArray b(blen); for (int i = 0; i < blen; ++i) b[i] = (uchar)before.latin1()[i]; @@ -2099,7 +2102,7 @@ QString &QString::replace(const QString &before, const QLatin1String &after, Qt::CaseSensitivity cs) { - int alen = qstrlen(after.latin1()); + int alen = after.size(); QVarLengthArray a(alen); for (int i = 0; i < alen; ++i) a[i] = (uchar)after.latin1()[i]; @@ -2120,7 +2123,7 @@ QString &QString::replace(const QString &before, */ QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs) { - int alen = qstrlen(after.latin1()); + int alen = after.size(); QVarLengthArray a(alen); for (int i = 0; i < alen; ++i) a[i] = (uchar)after.latin1()[i]; @@ -2150,20 +2153,23 @@ bool QString::operator==(const QString &other) const */ bool QString::operator==(const QLatin1String &other) const { + if (d->size != other.size()) + return false; + + if (!other.size()) + return isEmpty(); + const ushort *uc = d->data(); const ushort *e = uc + d->size; const uchar *c = (uchar *)other.latin1(); - if (!c) - return isEmpty(); - - while (*c) { - if (uc == e || *uc != *c) + while (uc < e) { + if (*uc != *c) return false; ++uc; ++c; } - return (uc == e); + return true; } /*! \fn bool QString::operator==(const QByteArray &other) const @@ -2212,20 +2218,20 @@ bool QString::operator<(const QString &other) const */ bool QString::operator<(const QLatin1String &other) const { - const ushort *uc = d->data(); - const ushort *e = uc + d->size; const uchar *c = (uchar *) other.latin1(); - if (!c || *c == 0) return false; - while (*c) { - if (uc == e || *uc != *c) + const ushort *uc = d->data(); + const ushort *e = uc + qMin(d->size, other.size()); + + while (uc < e) { + if (*uc != *c) break; ++uc; ++c; } - return (uc == e ? *c : *uc < *c); + return (uc == (d->data() + d->size) ? *c : *uc < *c); } /*! \fn bool QString::operator<(const QByteArray &other) const @@ -2314,20 +2320,20 @@ bool QString::operator<(const QLatin1String &other) const */ bool QString::operator>(const QLatin1String &other) const { - const ushort *uc = d->data();; - const ushort *e = uc + d->size; const uchar *c = (uchar *) other.latin1(); - if (!c || *c == '\0') return !isEmpty(); - while (*c) { - if (uc == e || *uc != *c) + const ushort *uc = d->data();; + const ushort *e = uc + qMin(d->size, other.size()); + + while (uc < e) { + if (*uc != *c) break; ++uc; ++c; } - return (uc == e ? false : *uc > *c); + return (uc == (d->data() + d->size) ? false : *uc > *c); } /*! \fn bool QString::operator>(const QByteArray &other) const @@ -2696,7 +2702,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c */ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const { - const int sl = qstrlen(str.latin1()); + const int sl = str.size(); if (sl == 1) return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); @@ -3832,7 +3838,7 @@ QString QString::fromLocal8Bit(const char *str, int size) if (!str) return QString(); if (size == 0 || (!*str && size < 0)) - return QLatin1String(""); + return QString(shared_empty); #if !defined(QT_NO_TEXTCODEC) if (size < 0) size = qstrlen(str); @@ -7468,7 +7474,7 @@ QDataStream &operator>>(QDataStream &in, QString &str) } } } else { - str = QLatin1String(""); + str = QString(QLatin1String("")); } } return in; @@ -8440,7 +8446,7 @@ int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - const int sl = qstrlen(str.latin1()); + const int sl = str.size(); if (sl == 1) return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); @@ -8793,7 +8799,7 @@ static inline int qt_find_latin1_string(const QChar *haystack, int size, int from, Qt::CaseSensitivity cs) { const char *latin1 = needle.latin1(); - int len = qstrlen(latin1); + int len = needle.size(); QVarLengthArray s(len); for (int i = 0; i < len; ++i) s[i] = latin1[i]; @@ -8834,7 +8840,7 @@ static inline bool qt_starts_with(const QChar *haystack, int haystackLen, return !needle.latin1(); if (haystackLen == 0) return !needle.latin1() || *needle.latin1() == 0; - const int slen = qstrlen(needle.latin1()); + const int slen = needle.size(); if (slen > haystackLen) return false; const ushort *data = reinterpret_cast(haystack); @@ -8885,7 +8891,7 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen, return !needle.latin1(); if (haystackLen == 0) return !needle.latin1() || *needle.latin1() == 0; - const int slen = qstrlen(needle.latin1()); + const int slen = needle.size(); int pos = haystackLen - slen; if (pos < 0) return false; diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 81dff3d309..e0473e411a 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -610,11 +610,11 @@ public: class Q_CORE_EXPORT QLatin1String { public: - inline explicit QLatin1String(const char *s) : chars(s) {} - inline QLatin1String &operator=(const QLatin1String &other) - { chars = other.chars; return *this; } + inline explicit QLatin1String(const char *s) : m_size(s ? strlen(s) : 0), m_data(s) {} - inline const char *latin1() const { return chars; } + inline const char *latin1() const { return m_data; } + inline int size() const { return m_size; } + inline const char *data() const { return m_data; } inline bool operator==(const QString &s) const { return s == *this; } @@ -642,9 +642,12 @@ public: inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const { return QString::fromAscii(s) <= *this; } private: - const char *chars; + int m_size; + const char *m_data; }; +// Qt 4.x compatibility +typedef QLatin1String QLatin1Literal; inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLatin1.latin1())) diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index 1cc7e5d2c3..4c6848498b 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -44,47 +44,6 @@ QT_BEGIN_NAMESPACE -/*! - \class QLatin1Literal - \internal - \reentrant - \since 4.6 - - \brief The QLatin1Literal class provides a thin wrapper around string - literals used in source code. - - \ingroup tools - \ingroup shared - \ingroup string-processing - - - Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size - without iterating over the literal. - - The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder - to reduce the number of reallocations needed to build up a string from - smaller chunks. - - \sa QStringBuilder, QLatin1String, QString, QStringRef -*/ - -/*! \fn int QLatin1Literal::size() const - - Returns the number of characters in the literal \e{excluding} the trailing - NULL char. -*/ - -/*! \fn QLatin1Literal::QLatin1Literal(const char str) - - Constructs a new literal from the string \a str. -*/ - -/*! \fn const char *QLatin1Literal::data() const - - Returns a pointer to the first character of the string literal. - The string literal is terminated by a NUL character. -*/ - /*! \class QStringBuilder \internal @@ -110,7 +69,7 @@ QT_BEGIN_NAMESPACE The QStringBuilder class is not to be used explicitly in user code. Instances of the class are created as return values of the operator%() function, acting on objects of type QString, - QLatin1String, QLatin1Literal, QStringRef, QChar, QCharRef, + QLatin1String, QStringRef, QChar, QCharRef, QLatin1Char, and \c char. Concatenating strings with operator%() generally yields better @@ -118,7 +77,7 @@ QT_BEGIN_NAMESPACE if there are three or more of them, and performs equally well in other cases. - \sa QLatin1Literal, QString + \sa QLatin1String, QString */ /*! \fn QStringBuilder::QStringBuilder(const A &a, const B &b) @@ -132,7 +91,7 @@ QT_BEGIN_NAMESPACE takes a QString parameter. This function is usable with arguments of type \c QString, - \c QLatin1String, \c QLatin1Literal, \c QStringRef, + \c QLatin1String, \c QStringRef, \c QChar, \c QCharRef, \c QLatin1Char, and \c char. */ @@ -145,7 +104,7 @@ QT_BEGIN_NAMESPACE /*! \fn operator QStringBuilder::QString() const - Converts the \c QLatin1Literal into a \c QString object. + Converts the \c QLatin1String into a \c QString object. */ /*! \internal diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 594ab2f183..c86a51f8e3 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -59,22 +59,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -// ### Qt 5: merge with QLatin1String -class QLatin1Literal -{ -public: - int size() const { return m_size; } - const char *data() const { return m_data; } - - template - QLatin1Literal(const char (&str)[N]) - : m_size(N - 1), m_data(str) {} - -private: - const int m_size; - const char * const m_data; -}; - struct Q_CORE_EXPORT QAbstractConcatenable { protected: @@ -234,31 +218,13 @@ template <> struct QConcatenable typedef QLatin1String type; typedef QString ConvertTo; enum { ExactSize = true }; - static int size(const QLatin1String &a) { return qstrlen(a.latin1()); } + static int size(const QLatin1String &a) { return a.size(); } static inline void appendTo(const QLatin1String &a, QChar *&out) - { - for (const char *s = a.latin1(); *s; ) - *out++ = QLatin1Char(*s++); - } - static inline void appendTo(const QLatin1String &a, char *&out) - { - for (const char *s = a.latin1(); *s; ) - *out++ = *s++; - } -}; - -template <> struct QConcatenable -{ - typedef QLatin1Literal type; - typedef QString ConvertTo; - enum { ExactSize = true }; - static int size(const QLatin1Literal &a) { return a.size(); } - static inline void appendTo(const QLatin1Literal &a, QChar *&out) { for (const char *s = a.data(); *s; ) *out++ = QLatin1Char(*s++); } - static inline void appendTo(const QLatin1Literal &a, char *&out) + static inline void appendTo(const QLatin1String &a, char *&out) { for (const char *s = a.data(); *s; ) *out++ = *s++; -- cgit v1.2.3 From f96a19d1b474292940dab3a20194a88395aca8ed Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Thu, 7 Jul 2011 15:31:19 +0200 Subject: Fix a crash when D-Bus library can't be loaded In certain sandboxes, we have libQtDBus, but not D-Bus. QtDBus shouldn't crash in that case, but return non-working QDBusConnection instances instead. Change-Id: Ia4ac78d1197bae50cde0cf07e6fc66fc25b85011 Reviewed-on: http://codereview.qt.nokia.com/1319 Reviewed-by: Qt Sanity Bot Reviewed-by: Robert Griebl --- src/dbus/qdbus_symbols.cpp | 6 ++++++ src/dbus/qdbusconnection.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp index 44597c39b6..fed18350bb 100644 --- a/src/dbus/qdbus_symbols.cpp +++ b/src/dbus/qdbus_symbols.cpp @@ -62,6 +62,12 @@ void qdbus_unloadLibDBus() bool qdbus_loadLibDBus() { +#ifdef QT_BUILD_INTERNAL + // this is to simulate a library load failure for our autotest suite. + if (!qgetenv("QT_SIMULATE_DBUS_LIBFAIL").isEmpty()) + return false; +#endif + static volatile bool triedToLoadLibrary = false; #ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&qdbus_resolve_me)); diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 0b4133c8dd..9656903846 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -1061,7 +1061,7 @@ public: if (!instance) { qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.", type == SessionBus ? "session" : type == SystemBus ? "system" : "generic"); - } else { + } else if (QDBusConnectionPrivate::d(*this)) { QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread()); } } -- cgit v1.2.3 From 27b953efae3bbd02509d7d9d5c514cadf0e51d85 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Thu, 7 Jul 2011 17:02:42 +0200 Subject: Don't keep a static instance of QDBusConnection Prevents weird crashes at app exit and makes backtraces from potential crashes saner because they won't start in __cxa_init. Change-Id: I62821faad03b06ec92da05d96027b668d1f1ca0f Reviewed-on: http://codereview.qt.nokia.com/1324 Reviewed-by: Qt Sanity Bot Reviewed-by: Robert Griebl --- src/plugins/bearer/connman/qofonoservice_linux.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/plugins/bearer/connman/qofonoservice_linux.cpp b/src/plugins/bearer/connman/qofonoservice_linux.cpp index 7c0a255c17..d862456ddc 100644 --- a/src/plugins/bearer/connman/qofonoservice_linux.cpp +++ b/src/plugins/bearer/connman/qofonoservice_linux.cpp @@ -57,8 +57,6 @@ #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE -static QDBusConnection dbusConnection = QDBusConnection::systemBus(); - QOfonoManagerInterface::QOfonoManagerInterface( QObject *parent) : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), @@ -106,7 +104,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), QLatin1String(OFONO_MANAGER_PATH), QLatin1String(OFONO_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), @@ -256,7 +254,7 @@ void QOfonoModemInterface::connectNotify(const char *signal) QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_MODEM_INTERFACE), QLatin1String("PropertyChanged"), @@ -379,7 +377,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_NETWORK_REGISTRATION_INTERFACE), QLatin1String("PropertyChanged"), @@ -477,7 +475,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_NETWORK_OPERATOR_INTERFACE), QLatin1String("PropertyChanged"), @@ -580,7 +578,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_SIM_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), @@ -669,7 +667,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_DATA_CONNECTION_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), @@ -788,7 +786,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_DATA_CONTEXT_INTERFACE), QLatin1String("PropertyChanged"), @@ -870,7 +868,7 @@ void QOfonoSmsInterface::connectNotify(const char *signal) QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_SMS_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), -- cgit v1.2.3 From 7297cf8542f814a3afedfd85fb1824104a7b20b5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 5 Jul 2011 13:01:37 +0200 Subject: Don't cast a string from ascii Change-Id: Ia902e5be3ff61057b2e895a491bb68f1b7c6dd64 Reviewed-on: http://codereview.qt.nokia.com/1221 Reviewed-by: Qt Sanity Bot Reviewed-by: Liang Qi --- src/gui/text/qtextdocument.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 0abafb81cc..143dc1ab8c 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2710,7 +2710,7 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) html += QLatin1Char('>'); if (block.begin().atEnd()) - html += "
"; + html += QLatin1String("
"); QTextBlock::Iterator it = block.begin(); if (fragmentMarkers && !it.atEnd() && block == doc->begin()) -- cgit v1.2.3 From f3d6589068450283e9f147851113d1795b47acc6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 7 Jul 2011 16:10:31 +0200 Subject: Bugfix the QConstString implementation. Change-Id: Ic9ea9d91c1a976962a3881ecdf7ad178de768b08 Reviewed-on: http://codereview.qt.nokia.com/1349 Reviewed-by: Qt Sanity Bot Reviewed-by: Lars Knoll --- src/corelib/tools/qstring.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index fe6cae25d1..d2928003a4 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -800,8 +800,8 @@ const QString::Null QString::null = { }; \sa split() */ -const QConstStringData<1> QString::shared_null = (const QConstStringData<1>) { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } }; -const QConstStringData<1> QString::shared_empty = (const QConstStringData<1>) { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } }; +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 } }; int QString::grow(int size) { -- cgit v1.2.3 From 571785b31d21715857228b00f96cd24601b28c8c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 7 Jul 2011 19:51:09 +0200 Subject: Make the new QStringLiteral produce a non-temporary This is currently GCC-only code (the __extension ({ }) stuff), but it was the only way I found to create a static variable and return it. I had to add the QConstStringDataPtr container because I had to return a pointer to the data -- it's impossible to return a reference through this extension. I could have returned a naked pointer directly too. This isn't complete. GCC 4.6 is placing the string in the .data section, not .rodata as we wanted. Investigating further. Change-Id: I170030dca3eddbd69f6c879e952f652f7fe5d958 Reviewed-on: http://codereview.qt.nokia.com/1350 Reviewed-by: Lars Knoll --- src/corelib/tools/qstring.h | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index e0473e411a..c10af450b3 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -90,32 +90,54 @@ struct QStringData { inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } }; +template struct QConstStringData; +template struct QConstStringDataPtr +{ + const QConstStringData *ptr; +}; -#if defined(Q_COMPILER_UNICODE_STRINGS) +#if defined(Q_CC_GNU) +// We need to create a QStringData in the .rodata section of memory +// and the only way to do that is to create a "static const" variable. +// To do that, we need the __extension__ {( )} trick which only GCC supports +# if defined(Q_COMPILER_UNICODE_STRINGS) template struct QConstStringData { const QStringData str; const char16_t data[n]; operator const QStringData &() const { return str; } }; -#define QStringLiteral(str) (const QConstStringData) \ -{ { Q_REFCOUNT_INITIALIZER(-1), sizeof(u"" str)/2 -1, 0, 0, { 0 } }, u"" str } -// wchar_t is 2 bytes -#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) +# define QStringLiteral(str) \ + __extension__ ({ \ + enum { Size = sizeof(u"" str)/2 }; \ + static const QConstStringData qstring_literal = \ + { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, u"" str }; \ + QConstStringDataPtr holder = { &qstring_literal }; \ + holder; }) +# elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) +// wchar_t is 2 bytes template struct QConstStringData { const QStringData str; const wchar_t data[n]; operator const QStringData &() const { return str; } }; -#define QStringLiteral(str) (const QConstStringData) \ -{ { Q_REFCOUNT_INITIALIZER(-1), sizeof(L"" str)/2 -1, 0, 0, { 0 } }, L"" str } +# define QStringLiteral(str) \ + __extension__ ({ \ + enum { Size = sizeof(L"" str)/2 }; \ + static const QConstStringData qstring_literal = \ + { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, L"" str }; \ + QConstStringDataPtr holder = { &qstring_literal }; \ + holder; }) +# endif +#endif +#ifndef QStringLiteral +// not GCC, or GCC in C++98 mode with 4-byte wchar_t // fallback, uses QLatin1String as next best options -#else template struct QConstStringData { @@ -123,8 +145,7 @@ template struct QConstStringData const ushort data[n]; operator const QStringData &() const { return str; } }; -#define QStringLiteral(str) QLatin1String(str) - +# define QStringLiteral(str) QLatin1String(str) #endif #ifndef QT_NO_KEYWORDS @@ -558,6 +579,8 @@ public: QString(int size, Qt::Initialization); template inline QString(const QConstStringData &dd) : d(const_cast(&dd.str)) {} + template + inline QString(QConstStringDataPtr dd) : d(const_cast(&dd.ptr->str)) {} private: #if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) -- cgit v1.2.3 From a21f99292567418c620ccf2ffbb13946cac03b8d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 7 Jul 2011 19:53:35 +0200 Subject: Add support for QStringLiterals in QStringBuilder Otherwise we get errors for failing to have operator+ properly when writing: QStringLiteral("foo") + s Change-Id: I03844c95e9fdfa886eadfa2b5fe104ff048fd618 Reviewed-on: http://codereview.qt.nokia.com/1351 Reviewed-by: Qt Sanity Bot Reviewed-by: Lars Knoll --- src/corelib/tools/qstringbuilder.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index c86a51f8e3..6d998b62aa 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -249,6 +249,23 @@ template <> struct QConcatenable : private QAbstractConcatenable #endif }; +template struct QConcatenable > : private QAbstractConcatenable +{ + typedef QConstStringDataPtr type; + typedef QString ConvertTo; + enum { ExactSize = true }; + static int size(const type &) { return N; } + static inline void appendTo(const type &a, QChar *&out) + { + memcpy(out, reinterpret_cast(a.ptr->data), sizeof(QChar) * N); + out += N; + } +#ifndef QT_NO_CAST_TO_ASCII + static inline QT_ASCII_CAST_WARN void appendTo(const type &a, char *&out) + { convertToAscii(a.ptr->data, N, out); } +#endif +}; + template <> struct QConcatenable : private QAbstractConcatenable { typedef QStringRef type; -- cgit v1.2.3 From 62481fe9f6f7445600a5b3820bbdfc422ca85d52 Mon Sep 17 00:00:00 2001 From: Martin Zielinski Date: Mon, 4 Jul 2011 09:41:26 +0200 Subject: Fixed wayland windowmanager-protocol authorization The authorization is now handled more robust. The client tries to authenticate as soon as a surface is created, but does so only if the authentication token is valid. A re-authorization than happens when requestActivateWindow() is called. This is needed to get the auth-process properly working even with pre-started clients, that do not have a valid token on surface-creation time. Change-Id: I4371b424686b9d5a6a163a802ec66a33c0aeeea7 Reviewed-on: http://codereview.qt.nokia.com/1207 Reviewed-by: Qt Sanity Bot Reviewed-by: Lasse Holmstedt --- .../xcomposite_egl/qwaylandxcompositeeglwindow.cpp | 11 +++++++++++ .../xcomposite_egl/qwaylandxcompositeeglwindow.h | 1 + .../qwaylandwindowmanagerintegration.cpp | 9 ++++----- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp index 3daf5f6196..1047cb8b0a 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "qwaylandxcompositeeglwindow.h" +#include "qwaylandxcompositeeglintegration.h" +#include "windowmanager_integration/qwaylandwindowmanagerintegration.h" #include @@ -75,3 +77,12 @@ void QWaylandXCompositeEGLWindow::setGeometry(const QRect &rect) mContext->geometryChanged(); } } + +void QWaylandXCompositeEGLWindow::requestActivateWindow() +{ +#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT + mDisplay->windowManagerIntegration()->authenticateWithToken(); +#endif + + QWaylandWindow::requestActivateWindow(); +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h index 707801905d..ea4dd2d626 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h @@ -55,6 +55,7 @@ public: QPlatformGLContext *glContext() const; void setGeometry(const QRect &rect); + void requestActivateWindow(); private: QWaylandXCompositeEGLIntegration *mGlxIntegration; diff --git a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp index 7390c52740..60b0a5605e 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp @@ -99,19 +99,18 @@ void QWaylandWindowManagerIntegration::authenticateWithToken(const QByteArray &t QByteArray authToken = token; if (authToken.isEmpty()) authToken = qgetenv("WL_AUTHENTICATION_TOKEN"); - if (mWaylandWindowManager) + + if (mWaylandWindowManager && !authToken.isEmpty()) { wl_windowmanager_authenticate_with_token(mWaylandWindowManager, authToken.constData()); + } } void QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange(void *data, struct wl_windowmanager *wl_windowmanager, int visible) { Q_UNUSED(data); Q_UNUSED(wl_windowmanager); - QEvent evt(visible != 0 ? QEvent::ApplicationActivated : QEvent::ApplicationDeactivated); - + QEvent evt(visible != 0 ? QEvent::ApplicationActivate : QEvent::ApplicationDeactivate); QCoreApplication::sendEvent(QCoreApplication::instance(), &evt); - - qDebug() << "OnScreenVisibility" << (visible != 0); } void QWaylandWindowManagerIntegration::wlHandleScreenOrientationChange(void *data, struct wl_windowmanager *wl_windowmanager, int screenOrientation) -- cgit v1.2.3 From 948d051fb145ad486e0409cb219bab9616328502 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 7 Jul 2011 17:42:55 +0200 Subject: QNAM: Add support for more KnownHeaders Task-Number: QTBUG-17267 Change-Id: I32b41d26411ee3a7162bb658d69363a5eeb37230 Reviewed-on: http://codereview.qt.nokia.com/1327 Reviewed-by: Qt Sanity Bot Reviewed-by: Martin Petersson --- src/network/access/qnetworkrequest.cpp | 21 +++++++++++++++++++++ src/network/access/qnetworkrequest.h | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 7f61ef9239..21b1d84a78 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -105,6 +105,10 @@ QT_BEGIN_NAMESPACE header and contains a QList representing the cookies sent by the server to be stored locally. + \value UserAgentHeader The User-Agent header sent by HTTP clients. + + \value ServerHeader The Server header received by HTTP clients. + \sa header(), setHeader(), rawHeader(), setRawHeader() */ @@ -650,6 +654,12 @@ static QByteArray headerName(QNetworkRequest::KnownHeaders header) case QNetworkRequest::ContentDispositionHeader: return "Content-Disposition"; + case QNetworkRequest::UserAgentHeader: + return "User-Agent"; + + case QNetworkRequest::ServerHeader: + return "Server"; + // no default: // if new values are added, this will generate a compiler warning } @@ -663,6 +673,8 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria case QNetworkRequest::ContentTypeHeader: case QNetworkRequest::ContentLengthHeader: case QNetworkRequest::ContentDispositionHeader: + case QNetworkRequest::UserAgentHeader: + case QNetworkRequest::ServerHeader: return value.toByteArray(); case QNetworkRequest::LocationHeader: @@ -745,6 +757,13 @@ static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerNam case 's': if (qstricmp(headerName.constData(), "set-cookie") == 0) return QNetworkRequest::SetCookieHeader; + else if (qstricmp(headerName.constData(), "server") == 0) + return QNetworkRequest::ServerHeader; + break; + + case 'u': + if (qstricmp(headerName.constData(), "user-agent") == 0) + return QNetworkRequest::UserAgentHeader; break; } @@ -778,6 +797,8 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy { // header is always a valid value switch (header) { + case QNetworkRequest::UserAgentHeader: + case QNetworkRequest::ServerHeader: case QNetworkRequest::ContentTypeHeader: // copy exactly, convert to QString return QString::fromLatin1(value); diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index eedb0f6592..aa86007127 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -66,7 +66,9 @@ public: LastModifiedHeader, CookieHeader, SetCookieHeader, - ContentDispositionHeader // added for QMultipartMessage + ContentDispositionHeader, // added for QMultipartMessage + UserAgentHeader, + ServerHeader }; enum Attribute { HttpStatusCodeAttribute, -- cgit v1.2.3 From d96b7b809e614dd416709acec768529457120b9f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 8 Jul 2011 10:42:49 +0200 Subject: Use memmove in QListData::append(int) as regions overlap. It's undefined behaviour to memcpy regions with overlapping area. You have to use memmove. Change-Id: I912c819bf7ab26ba1e60028ee9d7c833dfc5138a Reviewed-on: http://codereview.qt.nokia.com/1355 Reviewed-by: Olivier Goffart --- src/corelib/tools/qlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 80c610be36..14dfc6a139 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -164,7 +164,7 @@ void **QListData::append(int n) if (b - n >= 2 * d->alloc / 3) { // we have enough space. Just not at the end -> move it. e -= b; - ::memcpy(d->array, d->array + b, e * sizeof(void *)); + ::memmove(d->array, d->array + b, e * sizeof(void *)); d->begin = 0; } else { realloc(grow(d->alloc + n)); -- cgit v1.2.3 From 2e58f52ded89e1d925f7129bc6c70a1a8b72f765 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 8 Jul 2011 11:11:39 +0200 Subject: Remove the qs() macro. There is tootoo many risks of conflicts with existing code. QStringLiteral is not that hard to type. And if users want to use qs they can still define it in their own headers. Change-Id: I7da4772d902033fa163f5177c012b5d0e87332d7 Reviewed-on: http://codereview.qt.nokia.com/1357 Reviewed-by: Lars Knoll --- src/corelib/tools/qstring.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index c10af450b3..de973a82fb 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -148,10 +148,6 @@ template struct QConstStringData # define QStringLiteral(str) QLatin1String(str) #endif -#ifndef QT_NO_KEYWORDS -#define qs(str) QStringLiteral(str) -#endif - class Q_CORE_EXPORT QString { public: -- cgit v1.2.3 From b59392aeb53fbba957d145b95a6111dcb18e15b1 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 7 Jul 2011 14:17:58 +0100 Subject: Fix memory leak in QHostInfo QHostInfo was leaking in the code path where it removes duplicate name lookups after one has completed. Task-number: QT-5121 Reviewed-by: Markus Goetz (cherry picked from commit 73df7890923f377f19147466d9317fe1ec064b1d) Change-Id: I26cc6a168ef8ea6cc18940300ca2eddd6777071d Reviewed-on: http://codereview.qt.nokia.com/1363 Reviewed-by: Qt Sanity Bot Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index df7766e2c5..d42c2598f8 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -527,6 +527,7 @@ void QHostInfoRunnable::run() iterator.remove(); hostInfo.setLookupId(postponed->id); postponed->resultEmitter.emitResultsReady(hostInfo); + delete postponed; } } } -- cgit v1.2.3 From 6efe729881303f2198d61817174e9695aea63246 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Mon, 4 Jul 2011 10:30:18 +0200 Subject: Remove more references to demos. Change-Id: I431184cd0534c86047706fdaa1045b2935de5d7a Reviewed-on: http://codereview.qt.nokia.com/1307 Reviewed-by: Qt Sanity Bot Reviewed-by: David Boddie --- src/gui/painting/qpainter.cpp | 2 +- src/plugins/platforms/uikit/README | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 8752cb86a7..686f2f023a 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1318,7 +1318,7 @@ void QPainterPrivate::updateState(QPainterState *newState) \o \inlineimage qpainter-compositiondemo.png \o - \bold {Composition Modes Demo} + \bold {Composition Modes Example} The \l {painting/composition}{Composition Modes} example, available in Qt's examples directory, allows you to experiment with the various diff --git a/src/plugins/platforms/uikit/README b/src/plugins/platforms/uikit/README index a101a3ac0b..f878cce50e 100644 --- a/src/plugins/platforms/uikit/README +++ b/src/plugins/platforms/uikit/README @@ -18,11 +18,11 @@ After configuring and building Qt you need to also build src/plugins/platforms/u Simulator: ---------- -configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations +configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations Device: ------- -configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations +configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations 2) XCode setup: - there are examples in the examples subdirectory of the platform plugin -- cgit v1.2.3 From cd80fcb5d6db9d99684b94a90d2c798b712442c4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 8 Jul 2011 14:10:02 +0200 Subject: Use lambdas for generating static data for QStringLiteral This means it will work on C++0x compilers that support lambdas (all of them once they've completed supporting the functionality). Olivier had the idea and the initial code. Change-Id: I11ef7da4058ed18f4ea99ada070891a68ed54f55 Reviewed-on: http://codereview.qt.nokia.com/1380 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/tools/qstring.h | 59 +++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index de973a82fb..2251b64430 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -96,28 +96,16 @@ template struct QConstStringDataPtr const QConstStringData *ptr; }; -#if defined(Q_CC_GNU) -// We need to create a QStringData in the .rodata section of memory -// and the only way to do that is to create a "static const" variable. -// To do that, we need the __extension__ {( )} trick which only GCC supports - -# if defined(Q_COMPILER_UNICODE_STRINGS) +#if defined(Q_COMPILER_UNICODE_STRINGS) template struct QConstStringData { const QStringData str; const char16_t data[n]; operator const QStringData &() const { return str; } }; +#define QT_QSTRING_UNICODE_MARKER u"" -# define QStringLiteral(str) \ - __extension__ ({ \ - enum { Size = sizeof(u"" str)/2 }; \ - static const QConstStringData qstring_literal = \ - { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, u"" str }; \ - QConstStringDataPtr holder = { &qstring_literal }; \ - holder; }) - -# elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) +#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) // wchar_t is 2 bytes template struct QConstStringData { @@ -125,26 +113,45 @@ template struct QConstStringData const wchar_t data[n]; operator const QStringData &() const { return str; } }; -# define QStringLiteral(str) \ +#define QT_QSTRING_UNICODE_MARKER L"" + +#else +template struct QConstStringData +{ + const QStringData str; + const ushort data[n]; + operator const QStringData &() const { return str; } +}; +#endif + +#if defined(QT_QSTRING_UNICODE_MARKER) +# if defined(Q_COMPILER_LAMBDA) +# define QStringLiteral(str) ([]() { \ + enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \ + static const QConstStringData qstring_literal = \ + { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \ + QConstStringDataPtr holder = { &qstring_literal }; \ + return holder; }()) + +# elif defined(Q_CC_GNU) +// We need to create a QStringData in the .rodata section of memory +// and the only way to do that is to create a "static const" variable. +// To do that, we need the __extension__ {( )} trick which only GCC supports + +# define QStringLiteral(str) \ __extension__ ({ \ - enum { Size = sizeof(L"" str)/2 }; \ + enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \ static const QConstStringData qstring_literal = \ - { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, L"" str }; \ + { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \ QConstStringDataPtr holder = { &qstring_literal }; \ holder; }) # endif #endif #ifndef QStringLiteral -// not GCC, or GCC in C++98 mode with 4-byte wchar_t +// no lambdas, not GCC, or GCC in C++98 mode with 4-byte wchar_t // fallback, uses QLatin1String as next best options -template struct QConstStringData -{ - const QStringData str; - const ushort data[n]; - operator const QStringData &() const { return str; } -}; # define QStringLiteral(str) QLatin1String(str) #endif @@ -576,7 +583,7 @@ public: template inline QString(const QConstStringData &dd) : d(const_cast(&dd.str)) {} template - inline QString(QConstStringDataPtr dd) : d(const_cast(&dd.ptr->str)) {} + Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr dd) : d(const_cast(&dd.ptr->str)) {} private: #if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) -- cgit v1.2.3 From 8cc3b1a42683c72b6c192ecfda28245dc561eeee Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 8 Jul 2011 15:41:50 +0200 Subject: Remove the definition of QT_NO_FPU based on the processor or WS The definition is just wrong these days. Modern ARMv7 and MIPS have FPUs. Maybe AVR32, SH or SH4A don't, but then QT_NO_FPU should be defined in the qplatformdefs.h for those platforms. More importantly, since QPA is the only supported architecture for Qt 5, we definitely don't want to say that no platforms have no FPU. Still let qreal be defined to float on ARM, though: on Cortex-A8, which is the current norm these days, float performance is better than double performance. Change-Id: I89e01c10c59fbe95840a668ec9736846d23258fb Merge-request: 16 Reviewed-by: Olivier Goffart Reviewed-on: http://codereview.qt.nokia.com/1383 Reviewed-by: Qt Sanity Bot --- src/corelib/global/qglobal.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 6c89e9b670..15145ced07 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1131,10 +1131,6 @@ redefine to built-in booleans to make autotests work properly */ typedef int QNoImplicitBoolCast; -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) -#define QT_NO_FPU -#endif - // This logic must match the one in qmetatype.h #if defined(QT_COORD_TYPE) typedef QT_COORD_TYPE qreal; -- cgit v1.2.3 From d9bec0a1d2d7ac18a9a8ae5eff8dd8204eb6bf70 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 8 Jul 2011 15:49:26 +0200 Subject: Remove Qt 4.3 binary compatibility for MSVC When we removed the useless "const" in the return type, we broke compatibility with a few compilers that include the return type in the mangling. We don't need that anymore in Qt 5. This change should have had a ### Qt5 mark everywhere, not just in a comment in qstring.cpp. Change-Id: I8839f8dc540b34e57a3efdb160a1c015f7328422 Merge-request: 13 Reviewed-by: Olivier Goffart Reviewed-on: http://codereview.qt.nokia.com/1385 Reviewed-by: Qt Sanity Bot --- src/corelib/tools/qbytearray.h | 20 -------------------- src/corelib/tools/qchar.cpp | 4 ---- src/corelib/tools/qchar.h | 15 --------------- src/corelib/tools/qstring.cpp | 4 ---- src/corelib/tools/qstring.h | 6 ------ 5 files changed, 49 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 9f54f1a831..26cf2af59c 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -172,15 +172,9 @@ public: inline bool isSharedWith(const QByteArray &other) const { return d == other.d; } void clear(); -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - const char at(int i) const; - const char operator[](int i) const; - const char operator[](uint i) const; -#else char at(int i) const; char operator[](int i) const; char operator[](uint i) const; -#endif QByteRef operator[](int i); QByteRef operator[](uint i); @@ -359,21 +353,12 @@ inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); } inline int QByteArray::size() const { return d->size; } -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE -inline const char QByteArray::at(int i) const -{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } -inline const char QByteArray::operator[](int i) const -{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } -inline const char QByteArray::operator[](uint i) const -{ Q_ASSERT(i < uint(size())); return d->data[i]; } -#else inline char QByteArray::at(int i) const { Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } inline char QByteArray::operator[](int i) const { Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } inline char QByteArray::operator[](uint i) const { Q_ASSERT(i < uint(size())); return d->data[i]; } -#endif inline bool QByteArray::isEmpty() const { return d->size == 0; } @@ -412,13 +397,8 @@ class Q_CORE_EXPORT QByteRef { : a(array),i(idx) {} friend class QByteArray; public: -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - inline operator const char() const - { return i < a.d->size ? a.d->data[i] : char(0); } -#else inline operator char() const { return i < a.d->size ? a.d->data[i] : char(0); } -#endif inline QByteRef &operator=(char c) { if (i >= a.d->size) a.expand(i); else a.detach(); a.d->data[i] = c; return *this; } diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 9db7d1ae83..475bd55de4 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -1295,11 +1295,7 @@ ushort QChar::toCaseFolded(ushort ucs2) \sa toLatin1(), unicode(), QTextCodec::codecForCStrings() */ -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE -const char QChar::toAscii() const -#else char QChar::toAscii() const -#endif { #ifndef QT_NO_CODEC_FOR_C_STRINGS if (QTextCodec::codecForCStrings()) diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index b7793403bd..cd30dace09 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -56,13 +56,8 @@ struct QLatin1Char { public: inline explicit QLatin1Char(char c) : ch(c) {} -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - inline const char toLatin1() const { return ch; } - inline const ushort unicode() const { return ushort(uchar(ch)); } -#else inline char toLatin1() const { return ch; } inline ushort unicode() const { return ushort(uchar(ch)); } -#endif private: char ch; @@ -230,15 +225,9 @@ public: UnicodeVersion unicodeVersion() const; -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - const char toAscii() const; - inline const char toLatin1() const; - inline const ushort unicode() const { return ucs; } -#else char toAscii() const; inline char toLatin1() const; inline ushort unicode() const { return ucs; } -#endif #ifdef Q_NO_PACKED_REFERENCE inline ushort &unicode() { return const_cast(ucs); } #else @@ -339,11 +328,7 @@ Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE); inline QChar::QChar() : ucs(0) {} -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE -inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } -#else inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } -#endif inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); } inline QChar::QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){} diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index d2928003a4..dab281cdf8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3636,10 +3636,6 @@ QByteArray QString::toLatin1() const return toLatin1_helper(unicode(), length()); } -// ### Qt 5: Change the return type of at least toAscii(), -// toLatin1() and unicode() such that the use of Q_COMPILER_MANGLES_RETURN_TYPE -// isn't necessary in the header. See task 177402. - /*! Returns an 8-bit representation of the string as a QByteArray. diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 2251b64430..34f160e782 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -832,15 +832,9 @@ public: inline void setCell(uchar cell); inline void setRow(uchar row); -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - const char toAscii() const { return QChar(*this).toAscii(); } - const char toLatin1() const { return QChar(*this).toLatin1(); } - const ushort unicode() const { return QChar(*this).unicode(); } -#else char toAscii() const { return QChar(*this).toAscii(); } char toLatin1() const { return QChar(*this).toLatin1(); } ushort unicode() const { return QChar(*this).unicode(); } -#endif ushort& unicode() { return s.data()[i].unicode(); } }; -- cgit v1.2.3 From c82af87b5375eacaabc81b8fe7e75f83d27bc6e5 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 11 Jul 2011 10:47:16 +0200 Subject: QSslSocket: Add accessors for SSL version This commit adds accessors for both the openssl version number and the version string. The intention here is to aid debugging by making it possible for applications to know which version of the openssl library has been found by the runtime linking code. Since the version of openssl in use will depend on the installation of the developer, the test cases merely display the version string and number rather than verifying that any particular version is in use. Change-Id: Ieec44f0941f99887c85c2858bab0481722d739e5 Merge-request: 12 Reviewed-by: Peter Hartmann Reviewed-on: http://codereview.qt.nokia.com/1406 Reviewed-by: Qt Sanity Bot --- src/network/ssl/qsslsocket.cpp | 21 +++++++++++++++++++++ src/network/ssl/qsslsocket.h | 3 +++ src/network/ssl/qsslsocket_openssl.cpp | 17 +++++++++++++++++ src/network/ssl/qsslsocket_openssl_symbols.cpp | 2 ++ src/network/ssl/qsslsocket_openssl_symbols_p.h | 1 + src/network/ssl/qsslsocket_p.h | 2 ++ 6 files changed, 46 insertions(+) (limited to 'src') diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index f191ed9324..20e520a3d5 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1598,6 +1598,27 @@ bool QSslSocket::supportsSsl() return QSslSocketPrivate::supportsSsl(); } +/*! + Returns the version number of the SSL library in use. Note that + this is the version of the library in use at run-time not compile + time. If no SSL support is available then this will return an + undefined value. +*/ +long QSslSocket::sslLibraryVersionNumber() +{ + return QSslSocketPrivate::opensslVersionNumber(); +} + +/*! + Returns the version string of the SSL library in use. Note that + this is the version of the library in use at run-time not compile + time. If no SSL support is available then this will return an empty value. +*/ +QString QSslSocket::sslLibraryVersionString() +{ + return QSslSocketPrivate::opensslVersionString(); +} + /*! Starts a delayed SSL handshake for a client connection. This function can be called when the socket is in the \l ConnectedState diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index f175ffd946..803e79e0c4 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -176,6 +176,9 @@ public: QList sslErrors() const; static bool supportsSsl(); + static long sslLibraryVersionNumber(); + static QString sslLibraryVersionString(); + void ignoreSslErrors(const QList &errors); public Q_SLOTS: diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 479a6bd60e..b87570b7bf 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -602,6 +602,23 @@ void QSslSocketPrivate::ensureInitialized() ensureCiphersAndCertsLoaded(); } +long QSslSocketPrivate::opensslVersionNumber() +{ + return q_SSLeay(); +} + +QString QSslSocketPrivate::opensslVersionString() +{ + if (!supportsSsl()) + return QString(); + + const char *versionString = q_SSLeay_version(SSLEAY_VERSION); + if (!versionString) + return QString(); + + return QString::fromLatin1(versionString); +} + /*! \internal diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index b652833b45..18a845b312 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -276,6 +276,7 @@ DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMM DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return) DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return) +DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return) #ifdef Q_OS_SYMBIAN #define RESOLVEFUNC(func, ordinal, lib) \ @@ -788,6 +789,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(OPENSSL_add_all_algorithms_conf) RESOLVEFUNC(SSL_CTX_load_verify_locations) RESOLVEFUNC(SSLeay) + RESOLVEFUNC(SSLeay_version) #endif // Q_OS_SYMBIAN symbolsResolved = true; delete libs.first; diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 658aa144a7..12b3890512 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -426,6 +426,7 @@ void q_OPENSSL_add_all_algorithms_noconf(); void q_OPENSSL_add_all_algorithms_conf(); int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath); long q_SSLeay(); +const char *q_SSLeay_version(int type); // Helper function class QDateTime; diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 86ecba07ce..c8ab820639 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -116,6 +116,8 @@ public: bool allowRootCertOnDemandLoading; static bool supportsSsl(); + static long opensslVersionNumber(); + static QString opensslVersionString(); static void ensureInitialized(); static void deinitialize(); static QList defaultCiphers(); -- cgit v1.2.3 From 915ec02cadcd6e3ca423968a094a97ad417783a1 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Wed, 6 Jul 2011 14:31:33 +0200 Subject: Remove some metrics parsing code from Core Text The respective value in some of the default fonts like Lucida Grande are simply not reliable. It seems that the only reliable way to get such information is by going through all the glyphs. It seems that these code are not well tested on Mac and should be removed for now since it caused visible regressions in QLineEdit rendering. Reviewed-by: Eskil (cherry picked from commit 8032d6f4ced50837e126f28c1475ad89eaf91ad7) Change-Id: I85e71a2e3228a367659be9f5f6ec3e667e0ce902 Reviewed-on: http://codereview.qt.nokia.com/1264 Reviewed-by: Qt Sanity Bot Reviewed-by: Jiang Jiang --- src/gui/text/qfontengine_coretext.mm | 20 +++----------------- src/gui/text/qfontengine_coretext_p.h | 3 --- 2 files changed, 3 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm index a68a1551d9..303da8d363 100644 --- a/src/gui/text/qfontengine_coretext.mm +++ b/src/gui/text/qfontengine_coretext.mm @@ -492,17 +492,6 @@ void QCoreTextFontEngine::init() avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize); } else avgCharWidth = QFontEngine::averageCharWidth(); - - ctMaxCharWidth = ctMinLeftBearing = ctMinRightBearing = 0; - QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); - if (hheaTable.size() >= 16) { - quint16 width = qFromBigEndian(reinterpret_cast(hheaTable.constData() + 10)); - ctMaxCharWidth = width * fontDef.pixelSize / emSize; - qint16 bearing = qFromBigEndian(reinterpret_cast(hheaTable.constData() + 12)); - ctMinLeftBearing = bearing * fontDef.pixelSize / emSize; - bearing = qFromBigEndian(reinterpret_cast(hheaTable.constData() + 14)); - ctMinRightBearing = bearing * fontDef.pixelSize / emSize; - } } bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, @@ -599,20 +588,17 @@ QFixed QCoreTextFontEngine::averageCharWidth() const qreal QCoreTextFontEngine::maxCharWidth() const { - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMaxCharWidth) : ctMaxCharWidth; + return 0; } qreal QCoreTextFontEngine::minLeftBearing() const { - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinLeftBearing) : ctMinLeftBearing; + return 0; } qreal QCoreTextFontEngine::minRightBearing() const { - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinRightBearing) : ctMinLeftBearing; + return 0; } void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) diff --git a/src/gui/text/qfontengine_coretext_p.h b/src/gui/text/qfontengine_coretext_p.h index b531856a27..d8a3033be6 100644 --- a/src/gui/text/qfontengine_coretext_p.h +++ b/src/gui/text/qfontengine_coretext_p.h @@ -107,9 +107,6 @@ private: int synthesisFlags; CGAffineTransform transform; QFixed avgCharWidth; - qreal ctMaxCharWidth; - qreal ctMinLeftBearing; - qreal ctMinRightBearing; friend class QCoreTextFontEngineMulti; }; -- cgit v1.2.3 From f9035587b98ac5dc9491e642b8ec84470ec03f0e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 23 Jun 2011 14:11:50 +0200 Subject: Replace try/catch blocks in favour of destructors in the event loop. This has two direct benefits: 1) compiles regardless of -fno-exceptions: no need for #ifndef QT_NO_EXCEPTIONS or QT_TRY/QT_CATCH 2) no QT_RETHROW either, which means the backtrace of an application crashing due to an uncaught exception will include the actual throw point. Change-Id: I18e5500e121bfa81431ef16699df96d962794f0e Reviewed-on: http://codereview.qt.nokia.com/663 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/kernel/qcoreapplication.cpp | 101 ++++++++++++++----------- src/corelib/kernel/qeventloop.cpp | 66 ++++++++-------- src/corelib/kernel/qobject.cpp | 130 +++++++++++++++++--------------- 3 files changed, 156 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 5f11b10ec5..2458f9649e 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -816,7 +816,16 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) // call overhead. QObjectPrivate *d = receiver->d_func(); QThreadData *threadData = d->threadData; - ++threadData->loopLevel; + + // Exception-safety without try/catch + struct Incrementer { + int &variable; + inline Incrementer(int &variable) : variable(variable) + { ++variable; } + inline ~Incrementer() + { --variable; } + }; + Incrementer inc(threadData->loopLevel); #ifdef QT_JAMBI_BUILD int deleteWatch = 0; @@ -827,12 +836,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) #endif bool returnValue; - QT_TRY { - returnValue = notify(receiver, event); - } QT_CATCH (...) { - --threadData->loopLevel; - QT_RETHROW; - } + returnValue = notify(receiver, event); #ifdef QT_JAMBI_BUILD // Restore the previous state if the object was not deleted.. @@ -841,7 +845,6 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) } QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch); #endif - --threadData->loopLevel; return returnValue; } @@ -1384,6 +1387,40 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset; data->postEventList.insertionOffset = data->postEventList.size(); + // Exception-safe cleaning up without the need for a try/catch block + struct CleanUp { + QObject *receiver; + int event_type; + QThreadData *data; + bool exceptionCaught; + + inline CleanUp(QObject *receiver, int event_type, QThreadData *data) : + receiver(receiver), event_type(event_type), data(data), exceptionCaught(true) + {} + inline ~CleanUp() + { + if (exceptionCaught) { + // since we were interrupted, we need another pass to make sure we clean everything up + data->canWait = false; + } + + --data->postEventList.recursion; + if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) + data->eventDispatcher->wakeUp(); + + // clear the global list, i.e. remove everything that was + // delivered. + if (!event_type && !receiver && data->postEventList.startOffset >= 0) { + const QPostEventList::iterator it = data->postEventList.begin(); + data->postEventList.erase(it, it + data->postEventList.startOffset); + data->postEventList.insertionOffset -= data->postEventList.startOffset; + Q_ASSERT(data->postEventList.insertionOffset >= 0); + data->postEventList.startOffset = 0; + } + } + }; + CleanUp cleanup(receiver, event_type, data); + while (i < data->postEventList.size()) { // avoid live-lock if (i >= data->postEventList.insertionOffset) @@ -1422,7 +1459,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // first, we diddle the event so that we can deliver // it, and that no one will try to touch it later. pe.event->posted = false; - QEvent * e = pe.event; + QScopedPointer e(pe.event); QObject * r = pe.receiver; --r->d_func()->postedEvents; @@ -1432,49 +1469,23 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // for the next event. const_cast(pe).event = 0; - locker.unlock(); - // after all that work, it's time to deliver the event. -#ifdef QT_NO_EXCEPTIONS - QCoreApplication::sendEvent(r, e); -#else - try { - QCoreApplication::sendEvent(r, e); - } catch (...) { - delete e; - locker.relock(); - - // since we were interrupted, we need another pass to make sure we clean everything up - data->canWait = false; - - // uglehack: copied from below - --data->postEventList.recursion; - if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) - data->eventDispatcher->wakeUp(); - throw; // rethrow - } -#endif + struct MutexUnlocker + { + QMutexLocker &m; + MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); } + ~MutexUnlocker() { m.relock(); } + }; + MutexUnlocker unlocker(locker); - delete e; - locker.relock(); + // after all that work, it's time to deliver the event. + QCoreApplication::sendEvent(r, e.data()); // careful when adding anything below this point - the // sendEvent() call might invalidate any invariants this // function depends on. } - --data->postEventList.recursion; - if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) - data->eventDispatcher->wakeUp(); - - // clear the global list, i.e. remove everything that was - // delivered. - if (!event_type && !receiver && data->postEventList.startOffset >= 0) { - const QPostEventList::iterator it = data->postEventList.begin(); - data->postEventList.erase(it, it + data->postEventList.startOffset); - data->postEventList.insertionOffset -= data->postEventList.startOffset; - Q_ASSERT(data->postEventList.insertionOffset >= 0); - data->postEventList.startOffset = 0; - } + cleanup.exceptionCaught = false; } /*! diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 5a4ce973bc..37c06a2093 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -184,49 +184,47 @@ int QEventLoop::exec(ProcessEventsFlags flags) qWarning("QEventLoop::exec: instance %p has already called exec()", this); return -1; } - d->inExec = true; - d->exit = false; - ++d->threadData->loopLevel; - d->threadData->eventLoops.push(this); - locker.unlock(); + + struct LoopReference { + QEventLoopPrivate *d; + QMutexLocker &locker; + + bool exceptionCaught; + LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true) + { + d->inExec = true; + d->exit = false; + ++d->threadData->loopLevel; + d->threadData->eventLoops.push(d->q_func()); + locker.unlock(); + } + + ~LoopReference() + { + if (exceptionCaught) { + qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" + "exceptions from an event handler is not supported in Qt. You must\n" + "reimplement QApplication::notify() and catch all exceptions there.\n"); + } + locker.relock(); + QEventLoop *eventLoop = d->threadData->eventLoops.pop(); + Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error"); + Q_UNUSED(eventLoop); // --release warning + d->inExec = false; + --d->threadData->loopLevel; + } + }; + LoopReference ref(d, locker); // remove posted quit events when entering a new event loop QCoreApplication *app = QCoreApplication::instance(); if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); -#if defined(QT_NO_EXCEPTIONS) while (!d->exit) processEvents(flags | WaitForMoreEvents | EventLoopExec); -#else - try { - while (!d->exit) - processEvents(flags | WaitForMoreEvents | EventLoopExec); - } catch (...) { - qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" - "exceptions from an event handler is not supported in Qt. You must\n" - "reimplement QApplication::notify() and catch all exceptions there.\n"); - - // copied from below - locker.relock(); - QEventLoop *eventLoop = d->threadData->eventLoops.pop(); - Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); - Q_UNUSED(eventLoop); // --release warning - d->inExec = false; - --d->threadData->loopLevel; - - throw; - } -#endif - - // copied above - locker.relock(); - QEventLoop *eventLoop = d->threadData->eventLoops.pop(); - Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); - Q_UNUSED(eventLoop); // --release warning - d->inExec = false; - --d->threadData->loopLevel; + ref.exceptionCaught = false; return d->returnCode; } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 192e0accaa..c1ac70d8da 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -125,6 +125,39 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } } +struct QConnectionSenderSwitcher { + QObject *receiver; + QObjectPrivate::Sender *previousSender; + QObjectPrivate::Sender currentSender; + bool switched; + + inline QConnectionSenderSwitcher() : switched(false) {} + + inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id) + { + switchSender(receiver, sender, signal_absolute_id); + } + + inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id) + { + this->receiver = receiver; + currentSender.sender = sender; + currentSender.signal = signal_absolute_id; + currentSender.ref = 1; + previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); + switched = true; + } + + inline ~QConnectionSenderSwitcher() + { + if (switched) + QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); + } +private: + Q_DISABLE_COPY(QConnectionSenderSwitcher) +}; + + void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0; @@ -1083,23 +1116,10 @@ bool QObject::event(QEvent *e) d_func()->inEventHandler = false; #endif QMetaCallEvent *mce = static_cast(e); - QObjectPrivate::Sender currentSender; - currentSender.sender = const_cast(mce->sender()); - currentSender.signal = mce->signalId(); - currentSender.ref = 1; - QObjectPrivate::Sender * const previousSender = - QObjectPrivate::setCurrentSender(this, ¤tSender); -#if defined(QT_NO_EXCEPTIONS) + + QConnectionSenderSwitcher sw(this, const_cast(mce->sender()), mce->signalId()); + mce->placeMetaCall(this); -#else - QT_TRY { - mce->placeMetaCall(this); - } QT_CATCH(...) { - QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender); - QT_RETHROW; - } -#endif - QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender); break; } @@ -2976,7 +2996,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, type &= Qt::UniqueConnection - 1; } - QObjectPrivate::Connection *c = new QObjectPrivate::Connection; + QScopedPointer c(new QObjectPrivate::Connection); c->sender = s; c->receiver = r; c->method_relative = method_index; @@ -2986,16 +3006,11 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, c->nextConnectionList = 0; c->callFunction = callFunction; - QT_TRY { - QObjectPrivate::get(s)->addConnection(signal_index, c); - } QT_CATCH(...) { - delete c; - QT_RETHROW; - } + QObjectPrivate::get(s)->addConnection(signal_index, c.data()); c->prev = &(QObjectPrivate::get(r)->senders); c->next = *c->prev; - *c->prev = c; + *c->prev = c.data(); if (c->next) c->next->prev = &c->next; @@ -3006,6 +3021,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f)); } + c.take(); // stop tracking return true; } @@ -3264,16 +3280,37 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign Qt::HANDLE currentThreadId = QThread::currentThreadId(); + { QMutexLocker locker(signalSlotLock(sender)); - QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists; - if (!connectionLists) { + struct ConnectionListsRef { + QObjectConnectionListVector *connectionLists; + ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists) + { + if (connectionLists) + ++connectionLists->inUse; + } + ~ConnectionListsRef() + { + if (!connectionLists) + return; + + --connectionLists->inUse; + Q_ASSERT(connectionLists->inUse >= 0); + if (connectionLists->orphaned) { + if (!connectionLists->inUse) + delete connectionLists; + } + } + + QObjectConnectionListVector *operator->() const { return connectionLists; } + }; + ConnectionListsRef connectionLists = sender->d_func()->connectionLists; + if (!connectionLists.connectionLists) { locker.unlock(); if (qt_signal_spy_callback_set.signal_end_callback != 0) qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index); return; } - ++connectionLists->inUse; - const QObjectPrivate::ConnectionList *list; if (signal_index < connectionLists->count()) @@ -3323,13 +3360,10 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign #endif } - QObjectPrivate::Sender currentSender; - QObjectPrivate::Sender *previousSender = 0; + QConnectionSenderSwitcher sw; + if (receiverInSameThread) { - currentSender.sender = sender; - currentSender.signal = signal_absolute_index; - currentSender.ref = 1; - previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); + sw.switchSender(receiver, sender, signal_absolute_index); } const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction; const int method_relative = c->method_relative; @@ -3354,23 +3388,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign argv ? argv : empty_argv); } -#if defined(QT_NO_EXCEPTIONS) metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); -#else - QT_TRY { - metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); - } QT_CATCH(...) { - locker.relock(); - if (receiverInSameThread) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned && !connectionLists->inUse) - delete connectionLists; - QT_RETHROW; - } -#endif if (qt_signal_spy_callback_set.slot_end_callback != 0) qt_signal_spy_callback_set.slot_end_callback(receiver, method); @@ -3378,9 +3396,6 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign locker.relock(); } - if (receiverInSameThread) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - if (connectionLists->orphaned) break; } while (c != last && (c = c->nextConnectionList) != 0); @@ -3391,17 +3406,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign //start over for all signals; ((list = &connectionLists->allsignals), true)); - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned) { - if (!connectionLists->inUse) - delete connectionLists; - } else if (connectionLists->dirty) { - sender->d_func()->cleanConnectionLists(); } - locker.unlock(); - if (qt_signal_spy_callback_set.signal_end_callback != 0) qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index); -- cgit v1.2.3 From 06f2c9da46b578b57f9baa9167946d77cd653914 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 8 Jul 2011 15:35:14 +0200 Subject: QNAM: Remove QNetworkAccessHttpBackend Qt 5.0 is using QNetworkReplyHttpImpl Change-Id: I230230dc8b81e55a6c0cc8e1d85714e49fd35d17 Reviewed-on: http://codereview.qt.nokia.com/1381 Reviewed-by: Qt Sanity Bot Reviewed-by: Martin Petersson --- .../access/qhttpnetworkconnectionchannel_p.h | 2 - src/network/access/qnetworkaccesshttpbackend.cpp | 1189 -------------------- src/network/access/qnetworkaccesshttpbackend_p.h | 169 --- src/network/access/qnetworkaccessmanager.cpp | 1 - src/network/access/qnetworkaccessmanager.h | 1 - 5 files changed, 1362 deletions(-) delete mode 100644 src/network/access/qnetworkaccesshttpbackend.cpp delete mode 100644 src/network/access/qnetworkaccesshttpbackend_p.h (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 8400f62ab9..c159f1a0c5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -163,8 +163,6 @@ public: bool isSocketWaiting() const; bool isSocketReading() const; - friend class QNetworkAccessHttpBackend; - protected slots: void _q_receiveReply(); void _q_bytesWritten(qint64 bytes); // proceed sending diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp deleted file mode 100644 index 64a22aa0e8..0000000000 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ /dev/null @@ -1,1189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork 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$ -** -****************************************************************************/ - -//#define QNETWORKACCESSHTTPBACKEND_DEBUG - -#include "qnetworkaccesshttpbackend_p.h" -#include "qnetworkaccessmanager_p.h" -#include "qnetworkaccesscache_p.h" -#include "qabstractnetworkcache.h" -#include "qnetworkrequest.h" -#include "qnetworkreply.h" -#include "QtNetwork/private/qnetworksession_p.h" -#include "qnetworkrequest_p.h" -#include "qnetworkcookie_p.h" -#include "QtCore/qdatetime.h" -#include "QtCore/qelapsedtimer.h" -#include "QtNetwork/qsslconfiguration.h" -#include "qhttpthreaddelegate_p.h" -#include "qthread.h" - -#ifndef QT_NO_HTTP - -#include // for strchr - -Q_DECLARE_METATYPE(QSharedPointer) - -QT_BEGIN_NAMESPACE - -class QNetworkProxy; - -static inline bool isSeparator(register char c) -{ - static const char separators[] = "()<>@,;:\\\"/[]?={}"; - return isLWS(c) || strchr(separators, c) != 0; -} - -// ### merge with nextField in cookiejar.cpp -static QHash parseHttpOptionHeader(const QByteArray &header) -{ - // The HTTP header is of the form: - // header = #1(directives) - // directives = token | value-directive - // value-directive = token "=" (token | quoted-string) - QHash result; - - int pos = 0; - while (true) { - // skip spaces - pos = nextNonWhitespace(header, pos); - if (pos == header.length()) - return result; // end of parsing - - // pos points to a non-whitespace - int comma = header.indexOf(',', pos); - int equal = header.indexOf('=', pos); - if (comma == pos || equal == pos) - // huh? Broken header. - return result; - - // The key name is delimited by either a comma, an equal sign or the end - // of the header, whichever comes first - int end = comma; - if (end == -1) - end = header.length(); - if (equal != -1 && end > equal) - end = equal; // equal sign comes before comma/end - QByteArray key = QByteArray(header.constData() + pos, end - pos).trimmed().toLower(); - pos = end + 1; - - if (uint(equal) < uint(comma)) { - // case: token "=" (token | quoted-string) - // skip spaces - pos = nextNonWhitespace(header, pos); - if (pos == header.length()) - // huh? Broken header - return result; - - QByteArray value; - value.reserve(header.length() - pos); - if (header.at(pos) == '"') { - // case: quoted-string - // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) - // qdtext = > - // quoted-pair = "\" CHAR - ++pos; - while (pos < header.length()) { - register char c = header.at(pos); - if (c == '"') { - // end of quoted text - break; - } else if (c == '\\') { - ++pos; - if (pos >= header.length()) - // broken header - return result; - c = header.at(pos); - } - - value += c; - ++pos; - } - } else { - // case: token - while (pos < header.length()) { - register char c = header.at(pos); - if (isSeparator(c)) - break; - value += c; - ++pos; - } - } - - result.insert(key, value); - - // find the comma now: - comma = header.indexOf(',', pos); - if (comma == -1) - return result; // end of parsing - pos = comma + 1; - } else { - // case: token - // key is already set - result.insert(key, QByteArray()); - } - } -} - -QNetworkAccessBackend * -QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op, - const QNetworkRequest &request) const -{ - // check the operation - switch (op) { - case QNetworkAccessManager::GetOperation: - case QNetworkAccessManager::PostOperation: - case QNetworkAccessManager::HeadOperation: - case QNetworkAccessManager::PutOperation: - case QNetworkAccessManager::DeleteOperation: - case QNetworkAccessManager::CustomOperation: - break; - - default: - // no, we can't handle this request - return 0; - } - - QUrl url = request.url(); - QString scheme = url.scheme().toLower(); - if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) - return new QNetworkAccessHttpBackend; - - return 0; -} - -QNetworkAccessHttpBackend::QNetworkAccessHttpBackend() - : QNetworkAccessBackend() - , statusCode(0) - , pendingDownloadDataEmissions(new QAtomicInt()) - , pendingDownloadProgressEmissions(new QAtomicInt()) - , loadingFromCache(false) - , usingZerocopyDownloadBuffer(false) -#ifndef QT_NO_OPENSSL - , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false) -#endif - , resumeOffset(0) -{ -} - -QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend() -{ - // This will do nothing if the request was already finished or aborted - emit abortHttpRequest(); - -#ifndef QT_NO_OPENSSL - delete pendingSslConfiguration; -#endif -} - -/* - For a given httpRequest - 1) If AlwaysNetwork, return - 2) If we have a cache entry for this url populate headers so the server can return 304 - 3) Calculate if response_is_fresh and if so send the cache and set loadedFromCache to true - */ -bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest) -{ - QNetworkRequest::CacheLoadControl CacheLoadControlAttribute = - (QNetworkRequest::CacheLoadControl)request().attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(); - if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork) { - // If the request does not already specify preferred cache-control - // force reload from the network and tell any caching proxy servers to reload too - if (!request().rawHeaderList().contains("Cache-Control")) { - httpRequest.setHeaderField("Cache-Control", "no-cache"); - httpRequest.setHeaderField("Pragma", "no-cache"); - } - return false; - } - - // The disk cache API does not currently support partial content retrieval. - // That is why we don't use the disk cache for any such requests. - if (request().hasRawHeader("Range")) - return false; - - QAbstractNetworkCache *nc = networkCache(); - if (!nc) - return false; // no local cache - - QNetworkCacheMetaData metaData = nc->metaData(url()); - if (!metaData.isValid()) - return false; // not in cache - - if (!metaData.saveToDisk()) - return false; - - QNetworkHeadersPrivate cacheHeaders; - QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); - - it = cacheHeaders.findRawHeader("etag"); - if (it != cacheHeaders.rawHeaders.constEnd()) - httpRequest.setHeaderField("If-None-Match", it->second); - - QDateTime lastModified = metaData.lastModified(); - if (lastModified.isValid()) - httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified)); - - it = cacheHeaders.findRawHeader("Cache-Control"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - QHash cacheControl = parseHttpOptionHeader(it->second); - if (cacheControl.contains("must-revalidate")) - return false; - } - - QDateTime currentDateTime = QDateTime::currentDateTime(); - QDateTime expirationDate = metaData.expirationDate(); - -#if 0 - /* - * age_value - * is the value of Age: header received by the cache with - * this response. - * date_value - * is the value of the origin server's Date: header - * request_time - * is the (local) time when the cache made the request - * that resulted in this cached response - * response_time - * is the (local) time when the cache received the - * response - * now - * is the current (local) time - */ - int age_value = 0; - it = cacheHeaders.findRawHeader("age"); - if (it != cacheHeaders.rawHeaders.constEnd()) - age_value = it->second.toInt(); - - QDateTime dateHeader; - int date_value = 0; - it = cacheHeaders.findRawHeader("date"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - dateHeader = QNetworkHeadersPrivate::fromHttpDate(it->second); - date_value = dateHeader.toTime_t(); - } - - int now = currentDateTime.toUTC().toTime_t(); - int request_time = now; - int response_time = now; - - // Algorithm from RFC 2616 section 13.2.3 - int apparent_age = qMax(0, response_time - date_value); - int corrected_received_age = qMax(apparent_age, age_value); - int response_delay = response_time - request_time; - int corrected_initial_age = corrected_received_age + response_delay; - int resident_time = now - response_time; - int current_age = corrected_initial_age + resident_time; - - // RFC 2616 13.2.4 Expiration Calculations - if (!expirationDate.isValid()) { - if (lastModified.isValid()) { - int diff = currentDateTime.secsTo(lastModified); - expirationDate = lastModified; - expirationDate.addSecs(diff / 10); - if (httpRequest.headerField("Warning").isEmpty()) { - QDateTime dt; - dt.setTime_t(current_age); - if (dt.daysTo(currentDateTime) > 1) - httpRequest.setHeaderField("Warning", "113"); - } - } - } - - // the cache-saving code below sets the expirationDate with date+max_age - // if "max-age" is present, or to Expires otherwise - int freshness_lifetime = dateHeader.secsTo(expirationDate); - bool response_is_fresh = (freshness_lifetime > current_age); -#else - bool response_is_fresh = currentDateTime.secsTo(expirationDate) >= 0; -#endif - - if (!response_is_fresh) - return false; - -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "response_is_fresh" << CacheLoadControlAttribute; -#endif - return sendCacheContents(metaData); -} - -static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio) -{ - switch (prio) { - case QNetworkRequest::LowPriority: - return QHttpNetworkRequest::LowPriority; - case QNetworkRequest::HighPriority: - return QHttpNetworkRequest::HighPriority; - case QNetworkRequest::NormalPriority: - default: - return QHttpNetworkRequest::NormalPriority; - } -} - -void QNetworkAccessHttpBackend::postRequest() -{ - QThread *thread = 0; - if (isSynchronous()) { - // A synchronous HTTP request uses its own thread - thread = new QThread(); - QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - thread->start(); - } else if (!manager->httpThread) { - // We use the manager-global thread. - // At some point we could switch to having multiple threads if it makes sense. - manager->httpThread = new QThread(); - QObject::connect(manager->httpThread, SIGNAL(finished()), manager->httpThread, SLOT(deleteLater())); - manager->httpThread->start(); -#ifndef QT_NO_NETWORKPROXY - qRegisterMetaType("QNetworkProxy"); -#endif -#ifndef QT_NO_OPENSSL - qRegisterMetaType >("QList"); - qRegisterMetaType("QSslConfiguration"); -#endif - qRegisterMetaType > >("QList >"); - qRegisterMetaType("QHttpNetworkRequest"); - qRegisterMetaType("QNetworkReply::NetworkError"); - qRegisterMetaType >("QSharedPointer"); - - thread = manager->httpThread; - } else { - // Asynchronous request, thread already exists - thread = manager->httpThread; - } - - QUrl url = request().url(); - httpRequest.setUrl(url); - - bool ssl = url.scheme().toLower() == QLatin1String("https"); - setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl); - httpRequest.setSsl(ssl); - - -#ifndef QT_NO_NETWORKPROXY - QNetworkProxy transparentProxy, cacheProxy; - - foreach (const QNetworkProxy &p, proxyList()) { - // use the first proxy that works - // for non-encrypted connections, any transparent or HTTP proxy - // for encrypted, only transparent proxies - if (!ssl - && (p.capabilities() & QNetworkProxy::CachingCapability) - && (p.type() == QNetworkProxy::HttpProxy || - p.type() == QNetworkProxy::HttpCachingProxy)) { - cacheProxy = p; - transparentProxy = QNetworkProxy::NoProxy; - break; - } - if (p.isTransparentProxy()) { - transparentProxy = p; - cacheProxy = QNetworkProxy::NoProxy; - break; - } - } - - // check if at least one of the proxies - if (transparentProxy.type() == QNetworkProxy::DefaultProxy && - cacheProxy.type() == QNetworkProxy::DefaultProxy) { - // unsuitable proxies - QMetaObject::invokeMethod(this, "error", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection, - Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError), - Q_ARG(QString, tr("No suitable proxy found"))); - QMetaObject::invokeMethod(this, "finished", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection); - return; - } -#endif - - - bool loadedFromCache = false; - httpRequest.setPriority(convert(request().priority())); - - switch (operation()) { - case QNetworkAccessManager::GetOperation: - httpRequest.setOperation(QHttpNetworkRequest::Get); - loadedFromCache = loadFromCacheIfAllowed(httpRequest); - break; - - case QNetworkAccessManager::HeadOperation: - httpRequest.setOperation(QHttpNetworkRequest::Head); - loadedFromCache = loadFromCacheIfAllowed(httpRequest); - break; - - case QNetworkAccessManager::PostOperation: - invalidateCache(); - httpRequest.setOperation(QHttpNetworkRequest::Post); - createUploadByteDevice(); - break; - - case QNetworkAccessManager::PutOperation: - invalidateCache(); - httpRequest.setOperation(QHttpNetworkRequest::Put); - createUploadByteDevice(); - break; - - case QNetworkAccessManager::DeleteOperation: - invalidateCache(); - httpRequest.setOperation(QHttpNetworkRequest::Delete); - break; - - case QNetworkAccessManager::CustomOperation: - invalidateCache(); // for safety reasons, we don't know what the operation does - httpRequest.setOperation(QHttpNetworkRequest::Custom); - createUploadByteDevice(); - httpRequest.setCustomVerb(request().attribute( - QNetworkRequest::CustomVerbAttribute).toByteArray()); - break; - - default: - break; // can't happen - } - - if (loadedFromCache) { - // commented this out since it will be called later anyway - // by copyFinished() - //QNetworkAccessBackend::finished(); - return; // no need to send the request! :) - } - - QList headers = request().rawHeaderList(); - if (resumeOffset != 0) { - if (headers.contains("Range")) { - // Need to adjust resume offset for user specified range - - headers.removeOne("Range"); - - // We've already verified that requestRange starts with "bytes=", see canResume. - QByteArray requestRange = request().rawHeader("Range").mid(6); - - int index = requestRange.indexOf('-'); - - quint64 requestStartOffset = requestRange.left(index).toULongLong(); - quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong(); - - requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) + - '-' + QByteArray::number(requestEndOffset); - - httpRequest.setHeaderField("Range", requestRange); - } else { - httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-'); - } - } - - foreach (const QByteArray &header, headers) - httpRequest.setHeaderField(header, request().rawHeader(header)); - - if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true) - httpRequest.setPipeliningAllowed(true); - - if (static_cast - (request().attribute(QNetworkRequest::AuthenticationReuseAttribute, - QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual) - httpRequest.setWithCredentials(false); - - - // Create the HTTP thread delegate - QHttpThreadDelegate *delegate = new QHttpThreadDelegate; -#ifndef Q_NO_BEARERMANAGEMENT - QVariant v(property("_q_networksession")); - if (v.isValid()) - delegate->networkSession = qvariant_cast >(v); -#endif - - // For the synchronous HTTP, this is the normal way the delegate gets deleted - // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished - connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater())); - - // Set the properties it needs - delegate->httpRequest = httpRequest; -#ifndef QT_NO_NETWORKPROXY - delegate->cacheProxy = cacheProxy; - delegate->transparentProxy = transparentProxy; -#endif - delegate->ssl = ssl; -#ifndef QT_NO_OPENSSL - if (ssl) - delegate->incomingSslConfiguration = request().sslConfiguration(); -#endif - - // Do we use synchronous HTTP? - delegate->synchronous = isSynchronous(); - - // The authentication manager is used to avoid the BlockingQueuedConnection communication - // from HTTP thread to user thread in some cases. - delegate->authenticationManager = manager->authenticationManager; - - if (!isSynchronous()) { - // Tell our zerocopy policy to the delegate - delegate->downloadBufferMaximumSize = - request().attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute).toLongLong(); - - // These atomic integers are used for signal compression - delegate->pendingDownloadData = pendingDownloadDataEmissions; - delegate->pendingDownloadProgress = pendingDownloadProgressEmissions; - - // Connect the signals of the delegate to us - connect(delegate, SIGNAL(downloadData(QByteArray)), - this, SLOT(replyDownloadData(QByteArray)), - Qt::QueuedConnection); - connect(delegate, SIGNAL(downloadFinished()), - this, SLOT(replyFinished()), - Qt::QueuedConnection); - connect(delegate, SIGNAL(downloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64)), - this, SLOT(replyDownloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64)), - Qt::QueuedConnection); - connect(delegate, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(replyDownloadProgressSlot(qint64,qint64)), - Qt::QueuedConnection); - connect(delegate, SIGNAL(error(QNetworkReply::NetworkError,QString)), - this, SLOT(httpError(QNetworkReply::NetworkError, const QString)), - Qt::QueuedConnection); -#ifndef QT_NO_OPENSSL - connect(delegate, SIGNAL(sslConfigurationChanged(QSslConfiguration)), - this, SLOT(replySslConfigurationChanged(QSslConfiguration)), - Qt::QueuedConnection); -#endif - // Those need to report back, therefire BlockingQueuedConnection - connect(delegate, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)), - this, SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)), - Qt::BlockingQueuedConnection); -#ifndef QT_NO_NETWORKPROXY - connect (delegate, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - Qt::BlockingQueuedConnection); -#endif -#ifndef QT_NO_OPENSSL - connect(delegate, SIGNAL(sslErrors(QList,bool*,QList*)), - this, SLOT(replySslErrors(const QList &, bool *, QList *)), - Qt::BlockingQueuedConnection); -#endif - // This signal we will use to start the request. - connect(this, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest())); - connect(this, SIGNAL(abortHttpRequest()), delegate, SLOT(abortRequest())); - - if (uploadByteDevice) { - QNonContiguousByteDeviceThreadForwardImpl *forwardUploadDevice = - new QNonContiguousByteDeviceThreadForwardImpl(uploadByteDevice->atEnd(), uploadByteDevice->size()); - if (uploadByteDevice->isResetDisabled()) - forwardUploadDevice->disableReset(); - forwardUploadDevice->setParent(delegate); // needed to make sure it is moved on moveToThread() - delegate->httpRequest.setUploadByteDevice(forwardUploadDevice); - - // From main thread to user thread: - QObject::connect(this, SIGNAL(haveUploadData(QByteArray, bool, qint64)), - forwardUploadDevice, SLOT(haveDataSlot(QByteArray, bool, qint64)), Qt::QueuedConnection); - QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()), - forwardUploadDevice, SIGNAL(readyRead()), - Qt::QueuedConnection); - - // From http thread to user thread: - QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)), - this, SLOT(wantUploadDataSlot(qint64))); - QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)), - this, SLOT(sentUploadDataSlot(qint64))); - connect(forwardUploadDevice, SIGNAL(resetData(bool*)), - this, SLOT(resetUploadDataSlot(bool*)), - Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued! - } - } else if (isSynchronous()) { - connect(this, SIGNAL(startHttpRequestSynchronously()), delegate, SLOT(startRequestSynchronously()), Qt::BlockingQueuedConnection); - - if (uploadByteDevice) { - // For the synchronous HTTP use case the use thread (this one here) is blocked - // so we cannot use the asynchronous upload architecture. - // We therefore won't use the QNonContiguousByteDeviceThreadForwardImpl but directly - // use the uploadByteDevice provided to us by the QNetworkReplyImpl. - // The code that is in QNetworkReplyImplPrivate::setup() makes sure it is safe to use from a thread - // since it only wraps a QRingBuffer - delegate->httpRequest.setUploadByteDevice(uploadByteDevice.data()); - } - } - - - // Move the delegate to the http thread - delegate->moveToThread(thread); - // This call automatically moves the uploadDevice too for the asynchronous case. - - // Send an signal to the delegate so it starts working in the other thread - if (isSynchronous()) { - emit startHttpRequestSynchronously(); // This one is BlockingQueuedConnection, so it will return when all work is done - - if (delegate->incomingErrorCode != QNetworkReply::NoError) { - replyDownloadMetaData - (delegate->incomingHeaders, - delegate->incomingStatusCode, - delegate->incomingReasonPhrase, - delegate->isPipeliningUsed, - QSharedPointer(), - delegate->incomingContentLength); - httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail); - } else { - replyDownloadMetaData - (delegate->incomingHeaders, - delegate->incomingStatusCode, - delegate->incomingReasonPhrase, - delegate->isPipeliningUsed, - QSharedPointer(), - delegate->incomingContentLength); - replyDownloadData(delegate->synchronousDownloadData); - } - - // End the thread. It will delete itself from the finished() signal - thread->quit(); - - finished(); - } else { - emit startHttpRequest(); // Signal to the HTTP thread and go back to user. - } -} - -void QNetworkAccessHttpBackend::invalidateCache() -{ - QAbstractNetworkCache *nc = networkCache(); - if (nc) - nc->remove(url()); -} - -void QNetworkAccessHttpBackend::open() -{ - postRequest(); -} - -void QNetworkAccessHttpBackend::closeDownstreamChannel() -{ - // FIXME Maybe we can get rid of this whole architecture part -} - -void QNetworkAccessHttpBackend::downstreamReadyWrite() -{ - // FIXME Maybe we can get rid of this whole architecture part -} - -void QNetworkAccessHttpBackend::setDownstreamLimited(bool b) -{ - Q_UNUSED(b); - // We know that readBuffer maximum size limiting is broken since quite a while. - // The task to fix this is QTBUG-15065 -} - -void QNetworkAccessHttpBackend::replyDownloadData(QByteArray d) -{ - int pendingSignals = (int)pendingDownloadDataEmissions->fetchAndAddAcquire(-1) - 1; - - if (pendingSignals > 0) { - // Some more signal emissions to this slot are pending. - // Instead of writing the downstream data, we wait - // and do it in the next call we get - // (signal comppression) - pendingDownloadData.append(d); - return; - } - - pendingDownloadData.append(d); - d.clear(); - // We need to usa a copy for calling writeDownstreamData as we could - // possibly recurse into this this function when we call - // appendDownstreamDataSignalEmissions because the user might call - // processEvents() or spin an event loop when this occur. - QByteDataBuffer pendingDownloadDataCopy = pendingDownloadData; - pendingDownloadData.clear(); - writeDownstreamData(pendingDownloadDataCopy); -} - -void QNetworkAccessHttpBackend::replyFinished() -{ - // We are already loading from cache, we still however - // got this signal because it was posted already - if (loadingFromCache) - return; - - finished(); -} - -void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode) -{ - switch (statusCode) { - case 301: // Moved Permanently - case 302: // Found - case 303: // See Other - case 307: // Temporary Redirect - // What do we do about the caching of the HTML note? - // The response to a 303 MUST NOT be cached, while the response to - // all of the others is cacheable if the headers indicate it to be - QByteArray header = rawHeader("location"); - QUrl url = QUrl::fromEncoded(header); - if (!url.isValid()) - url = QUrl(QLatin1String(header)); - redirectionRequested(url); - } -} - -void QNetworkAccessHttpBackend::replyDownloadMetaData - (QList > hm, - int sc,QString rp,bool pu, - QSharedPointer db, - qint64 contentLength) -{ - statusCode = sc; - reasonPhrase = rp; - - // Download buffer - if (!db.isNull()) { - reply->setDownloadBuffer(db, contentLength); - usingZerocopyDownloadBuffer = true; - } else { - usingZerocopyDownloadBuffer = false; - } - - setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu); - - // reconstruct the HTTP header - QList > headerMap = hm; - QList >::ConstIterator it = headerMap.constBegin(), - end = headerMap.constEnd(); - QByteArray header; - - for (; it != end; ++it) { - QByteArray value = rawHeader(it->first); - if (!value.isEmpty()) { - if (qstricmp(it->first.constData(), "set-cookie") == 0) - value += '\n'; - else - value += ", "; - } - value += it->second; - setRawHeader(it->first, value); - } - - setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode); - setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); - - // is it a redirection? - checkForRedirect(statusCode); - - if (statusCode >= 500 && statusCode < 600) { - QAbstractNetworkCache *nc = networkCache(); - if (nc) { - QNetworkCacheMetaData metaData = nc->metaData(url()); - QNetworkHeadersPrivate cacheHeaders; - cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); - QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - it = cacheHeaders.findRawHeader("Cache-Control"); - bool mustReValidate = false; - if (it != cacheHeaders.rawHeaders.constEnd()) { - QHash cacheControl = parseHttpOptionHeader(it->second); - if (cacheControl.contains("must-revalidate")) - mustReValidate = true; - } - if (!mustReValidate && sendCacheContents(metaData)) - return; - } - } - - if (statusCode == 304) { -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Received a 304 from" << url(); -#endif - QAbstractNetworkCache *nc = networkCache(); - if (nc) { - QNetworkCacheMetaData oldMetaData = nc->metaData(url()); - QNetworkCacheMetaData metaData = fetchCacheMetaData(oldMetaData); - if (oldMetaData != metaData) - nc->updateMetaData(metaData); - if (sendCacheContents(metaData)) - return; - } - } - - - if (statusCode != 304 && statusCode != 303) { - if (!isCachingEnabled()) - setCachingEnabled(true); - } - - metaDataChanged(); -} - -void QNetworkAccessHttpBackend::replyDownloadProgressSlot(qint64 received, qint64 total) -{ - // we can be sure here that there is a download buffer - - int pendingSignals = (int)pendingDownloadProgressEmissions->fetchAndAddAcquire(-1) - 1; - if (pendingSignals > 0) { - // Let's ignore this signal and look at the next one coming in - // (signal comppression) - return; - } - - // Now do the actual notification of new bytes - writeDownstreamDataDownloadBuffer(received, total); -} - -void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &, - QAuthenticator *auth) -{ - authenticationRequired(auth); -} - -void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode, - const QString &errorString) -{ -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "http error!" << errorCode << errorString; -#endif - - error(errorCode, errorString); -} - -#ifndef QT_NO_OPENSSL -void QNetworkAccessHttpBackend::replySslErrors( - const QList &list, bool *ignoreAll, QList *toBeIgnored) -{ - // Go to generic backend - sslErrors(list); - // Check if the callback set any ignore and return this here to http thread - if (pendingIgnoreAllSslErrors) - *ignoreAll = true; - if (!pendingIgnoreSslErrorsList.isEmpty()) - *toBeIgnored = pendingIgnoreSslErrorsList; -} - -void QNetworkAccessHttpBackend::replySslConfigurationChanged(const QSslConfiguration &c) -{ - // Receiving the used SSL configuration from the HTTP thread - if (pendingSslConfiguration) - *pendingSslConfiguration = c; - else if (!c.isNull()) - pendingSslConfiguration = new QSslConfiguration(c); -} -#endif - -// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -void QNetworkAccessHttpBackend::resetUploadDataSlot(bool *r) -{ - *r = uploadByteDevice->reset(); -} - -// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -void QNetworkAccessHttpBackend::sentUploadDataSlot(qint64 amount) -{ - uploadByteDevice->advanceReadPointer(amount); -} - -// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -void QNetworkAccessHttpBackend::wantUploadDataSlot(qint64 maxSize) -{ - // call readPointer - qint64 currentUploadDataLength = 0; - char *data = const_cast(uploadByteDevice->readPointer(maxSize, currentUploadDataLength)); - // Let's make a copy of this data - QByteArray dataArray(data, currentUploadDataLength); - - // Communicate back to HTTP thread - emit haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size()); -} - -/* - A simple web page that can be used to test us: http://www.procata.com/cachetest/ - */ -bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &metaData) -{ - setCachingEnabled(false); - if (!metaData.isValid()) - return false; - - QAbstractNetworkCache *nc = networkCache(); - Q_ASSERT(nc); - QIODevice *contents = nc->data(url()); - if (!contents) { -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Can not send cache, the contents are 0" << url(); -#endif - return false; - } - contents->setParent(this); - - QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); - int status = attributes.value(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (status < 100) - status = 200; // fake it - - setAttribute(QNetworkRequest::HttpStatusCodeAttribute, status); - setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute)); - setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true); - - QNetworkCacheMetaData::RawHeaderList rawHeaders = metaData.rawHeaders(); - QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(), - end = rawHeaders.constEnd(); - for ( ; it != end; ++it) - setRawHeader(it->first, it->second); - - checkForRedirect(status); - - // This needs to be emitted in the event loop because it can be reached at - // the direct code path of qnam.get(...) before the user has a chance - // to connect any signals. - QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); - qRegisterMetaType("QIODevice*"); - QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents)); - - -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes"; -#endif - - // Set the following flag so we can ignore some signals from HTTP thread - // that would still come - loadingFromCache = true; - return true; -} - -void QNetworkAccessHttpBackend::copyFinished(QIODevice *dev) -{ - delete dev; - finished(); -} - -#ifndef QT_NO_OPENSSL -void QNetworkAccessHttpBackend::ignoreSslErrors() -{ - pendingIgnoreAllSslErrors = true; -} - -void QNetworkAccessHttpBackend::ignoreSslErrors(const QList &errors) -{ - // the pending list is set if QNetworkReply::ignoreSslErrors(const QList &errors) - // is called before QNetworkAccessManager::get() (or post(), etc.) - pendingIgnoreSslErrorsList = errors; -} - -void QNetworkAccessHttpBackend::fetchSslConfiguration(QSslConfiguration &config) const -{ - if (pendingSslConfiguration) - config = *pendingSslConfiguration; - else - config = request().sslConfiguration(); -} - -void QNetworkAccessHttpBackend::setSslConfiguration(const QSslConfiguration &newconfig) -{ - // Setting a SSL configuration on a reply is not supported. The user needs to set - // her/his QSslConfiguration on the QNetworkRequest. - Q_UNUSED(newconfig); -} -#endif - -QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetworkCacheMetaData &oldMetaData) const -{ - QNetworkCacheMetaData metaData = oldMetaData; - - QNetworkHeadersPrivate cacheHeaders; - cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); - QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - - QList newHeaders = rawHeaderList(); - foreach (QByteArray header, newHeaders) { - QByteArray originalHeader = header; - header = header.toLower(); - bool hop_by_hop = - (header == "connection" - || header == "keep-alive" - || header == "proxy-authenticate" - || header == "proxy-authorization" - || header == "te" - || header == "trailers" - || header == "transfer-encoding" - || header == "upgrade"); - if (hop_by_hop) - continue; - - // we are currently not using the date header to determine the expiration time of a page, - // but only the "Expires", "max-age" and "s-maxage" headers, see - // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()"). - if (header == "date") - continue; - - // Don't store Warning 1xx headers - if (header == "warning") { - QByteArray v = rawHeader(header); - if (v.length() == 3 - && v[0] == '1' - && v[1] >= '0' && v[1] <= '9' - && v[2] >= '0' && v[2] <= '9') - continue; - } - - it = cacheHeaders.findRawHeader(header); - if (it != cacheHeaders.rawHeaders.constEnd()) { - // Match the behavior of Firefox and assume Cache-Control: "no-transform" - if (header == "content-encoding" - || header == "content-range" - || header == "content-type") - continue; - - // For MS servers that send "Content-Length: 0" on 304 responses - // ignore this too - if (header == "content-length") - continue; - } - -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - QByteArray n = rawHeader(header); - QByteArray o; - if (it != cacheHeaders.rawHeaders.constEnd()) - o = (*it).second; - if (n != o && header != "date") { - qDebug() << "replacing" << header; - qDebug() << "new" << n; - qDebug() << "old" << o; - } -#endif - cacheHeaders.setRawHeader(originalHeader, rawHeader(header)); - } - metaData.setRawHeaders(cacheHeaders.rawHeaders); - - bool checkExpired = true; - - QHash cacheControl; - it = cacheHeaders.findRawHeader("Cache-Control"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - cacheControl = parseHttpOptionHeader(it->second); - QByteArray maxAge = cacheControl.value("max-age"); - if (!maxAge.isEmpty()) { - checkExpired = false; - QDateTime dt = QDateTime::currentDateTime(); - dt = dt.addSecs(maxAge.toInt()); - metaData.setExpirationDate(dt); - } - } - if (checkExpired) { - it = cacheHeaders.findRawHeader("expires"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - QDateTime expiredDateTime = QNetworkHeadersPrivate::fromHttpDate(it->second); - metaData.setExpirationDate(expiredDateTime); - } - } - - it = cacheHeaders.findRawHeader("last-modified"); - if (it != cacheHeaders.rawHeaders.constEnd()) - metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second)); - - bool canDiskCache; - // only cache GET replies by default, all other replies (POST, PUT, DELETE) - // are not cacheable by default (according to RFC 2616 section 9) - if (httpRequest.operation() == QHttpNetworkRequest::Get) { - - canDiskCache = true; - // 14.32 - // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client - // had sent "Cache-Control: no-cache". - it = cacheHeaders.findRawHeader("pragma"); - if (it != cacheHeaders.rawHeaders.constEnd() - && it->second == "no-cache") - canDiskCache = false; - - // HTTP/1.1. Check the Cache-Control header - if (cacheControl.contains("no-cache")) - canDiskCache = false; - else if (cacheControl.contains("no-store")) - canDiskCache = false; - - // responses to POST might be cacheable - } else if (httpRequest.operation() == QHttpNetworkRequest::Post) { - - canDiskCache = false; - // some pages contain "expires:" and "cache-control: no-cache" field, - // so we only might cache POST requests if we get "cache-control: max-age ..." - if (cacheControl.contains("max-age")) - canDiskCache = true; - - // responses to PUT and DELETE are not cacheable - } else { - canDiskCache = false; - } - - metaData.setSaveToDisk(canDiskCache); - QNetworkCacheMetaData::AttributesMap attributes; - if (statusCode != 304) { - // update the status code - attributes.insert(QNetworkRequest::HttpStatusCodeAttribute, statusCode); - attributes.insert(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); - } else { - // this is a redirection, keep the attributes intact - attributes = oldMetaData.attributes(); - } - metaData.setAttributes(attributes); - return metaData; -} - -bool QNetworkAccessHttpBackend::canResume() const -{ - // Only GET operation supports resuming. - if (operation() != QNetworkAccessManager::GetOperation) - return false; - - // Can only resume if server/resource supports Range header. - QByteArray acceptRangesheaderName("Accept-Ranges"); - if (!hasRawHeader(acceptRangesheaderName) || rawHeader(acceptRangesheaderName) == "none") - return false; - - // We only support resuming for byte ranges. - if (request().hasRawHeader("Range")) { - QByteArray range = request().rawHeader("Range"); - if (!range.startsWith("bytes=")) - return false; - } - - // If we're using a download buffer then we don't support resuming/migration - // right now. Too much trouble. - if (usingZerocopyDownloadBuffer) - return false; - - return true; -} - -void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset) -{ - resumeOffset = offset; -} - -QT_END_NAMESPACE - -#endif // QT_NO_HTTP diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h deleted file mode 100644 index 7d4ea56260..0000000000 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork 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 QNETWORKACCESSHTTPBACKEND_P_H -#define QNETWORKACCESSHTTPBACKEND_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the Network Access API. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qhttpnetworkconnection_p.h" -#include "qnetworkaccessbackend_p.h" -#include "qnetworkrequest.h" -#include "qnetworkreply.h" -#include "qabstractsocket.h" - -#include "QtCore/qpointer.h" -#include "QtCore/qdatetime.h" -#include "QtCore/qsharedpointer.h" -#include "qatomic.h" - -#ifndef QT_NO_HTTP - -QT_BEGIN_NAMESPACE - -class QNetworkAccessCachedHttpConnection; - -class QNetworkAccessHttpBackendIODevice; - -class QNetworkAccessHttpBackend: public QNetworkAccessBackend -{ - Q_OBJECT -public: - QNetworkAccessHttpBackend(); - virtual ~QNetworkAccessHttpBackend(); - - virtual void open(); - virtual void closeDownstreamChannel(); - - virtual void downstreamReadyWrite(); - virtual void setDownstreamLimited(bool b); - - virtual void copyFinished(QIODevice *); -#ifndef QT_NO_OPENSSL - virtual void ignoreSslErrors(); - virtual void ignoreSslErrors(const QList &errors); - - virtual void fetchSslConfiguration(QSslConfiguration &configuration) const; - virtual void setSslConfiguration(const QSslConfiguration &configuration); -#endif - QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const; - - // we return true since HTTP needs to send PUT/POST data again after having authenticated - bool needsResetableUploadData() { return true; } - - bool canResume() const; - void setResumeOffset(quint64 offset); - -signals: - // To HTTP thread: - void startHttpRequest(); - void abortHttpRequest(); - - void startHttpRequestSynchronously(); - - void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize); -private slots: - // From HTTP thread: - void replyDownloadData(QByteArray); - void replyFinished(); - void replyDownloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64); - void replyDownloadProgressSlot(qint64,qint64); - void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); - void httpError(QNetworkReply::NetworkError error, const QString &errorString); -#ifndef QT_NO_OPENSSL - void replySslErrors(const QList &, bool *, QList *); - void replySslConfigurationChanged(const QSslConfiguration&); -#endif - - // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread: - void resetUploadDataSlot(bool *r); - void wantUploadDataSlot(qint64); - void sentUploadDataSlot(qint64); - - bool sendCacheContents(const QNetworkCacheMetaData &metaData); - -private: - QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread - int statusCode; - QString reasonPhrase; - // Will be increased by HTTP thread: - QSharedPointer pendingDownloadDataEmissions; - QSharedPointer pendingDownloadProgressEmissions; - bool loadingFromCache; - QByteDataBuffer pendingDownloadData; - bool usingZerocopyDownloadBuffer; - -#ifndef QT_NO_OPENSSL - QSslConfiguration *pendingSslConfiguration; - bool pendingIgnoreAllSslErrors; - QList pendingIgnoreSslErrorsList; -#endif - - quint64 resumeOffset; - - bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest); - void invalidateCache(); - void postRequest(); - void readFromHttp(); - void checkForRedirect(const int statusCode); -}; - -class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory -{ -public: - virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op, - const QNetworkRequest &request) const; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_HTTP - -#endif diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 0b51f7255b..eba5880352 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -50,7 +50,6 @@ #include "QtNetwork/qnetworksession.h" #include "QtNetwork/private/qsharednetworksession_p.h" -#include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessftpbackend_p.h" #include "qnetworkaccessfilebackend_p.h" #include "qnetworkaccessdebugpipebackend_p.h" diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index ea295dbe97..8ce6080d3a 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -159,7 +159,6 @@ protected: private: friend class QNetworkReplyImplPrivate; - friend class QNetworkAccessHttpBackend; friend class QNetworkReplyHttpImpl; Q_DECLARE_PRIVATE(QNetworkAccessManager) -- cgit v1.2.3 From 0c0676ada2cc3943d09f8eb1e75491b80f08f27b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 8 Jul 2011 15:49:26 +0200 Subject: Remove #ifdef for platforms where QChar was packed -- there aren't any On ARM OABI, sizeof(QChar) was 4, so we used to pack it so QChar[] was isomorphic to ushort[]. We don't support the OABI anymore and the EABI does the right thing. Change-Id: I181dd2f169f6868450302e269ef9ad5d643f306f Merge-request: 13 Reviewed-by: Olivier Goffart Reviewed-on: http://codereview.qt.nokia.com/1386 Reviewed-by: Qt Sanity Bot --- src/corelib/tools/qchar.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index cd30dace09..d6db72d5ac 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -228,11 +228,7 @@ public: char toAscii() const; inline char toLatin1() const; inline ushort unicode() const { return ucs; } -#ifdef Q_NO_PACKED_REFERENCE - inline ushort &unicode() { return const_cast(ucs); } -#else inline ushort &unicode() { return ucs; } -#endif static QChar fromAscii(char c); static QChar fromLatin1(char c); -- cgit v1.2.3 From c299b4deac512f3d80c840e5eef2f18b2bc0b43c Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 11 Jul 2011 11:35:53 +0200 Subject: SSL internals: rename methods in the SSL backend to reflect public ones Change-Id: I234c740b1acbfea670d6170332626f5e3ba49328 Reviewed-on: http://codereview.qt.nokia.com/1437 Reviewed-by: Qt Sanity Bot Reviewed-by: Martin Petersson --- src/network/ssl/qsslsocket.cpp | 4 ++-- src/network/ssl/qsslsocket_openssl.cpp | 4 ++-- src/network/ssl/qsslsocket_p.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 20e520a3d5..294e2508d8 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1606,7 +1606,7 @@ bool QSslSocket::supportsSsl() */ long QSslSocket::sslLibraryVersionNumber() { - return QSslSocketPrivate::opensslVersionNumber(); + return QSslSocketPrivate::sslLibraryVersionNumber(); } /*! @@ -1616,7 +1616,7 @@ long QSslSocket::sslLibraryVersionNumber() */ QString QSslSocket::sslLibraryVersionString() { - return QSslSocketPrivate::opensslVersionString(); + return QSslSocketPrivate::sslLibraryVersionString(); } /*! diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index b87570b7bf..c7e938a705 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -602,12 +602,12 @@ void QSslSocketPrivate::ensureInitialized() ensureCiphersAndCertsLoaded(); } -long QSslSocketPrivate::opensslVersionNumber() +long QSslSocketPrivate::sslLibraryVersionNumber() { return q_SSLeay(); } -QString QSslSocketPrivate::opensslVersionString() +QString QSslSocketPrivate::sslLibraryVersionString() { if (!supportsSsl()) return QString(); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index c8ab820639..b1dc656e88 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -116,8 +116,8 @@ public: bool allowRootCertOnDemandLoading; static bool supportsSsl(); - static long opensslVersionNumber(); - static QString opensslVersionString(); + static long sslLibraryVersionNumber(); + static QString sslLibraryVersionString(); static void ensureInitialized(); static void deinitialize(); static QList defaultCiphers(); -- cgit v1.2.3 From 8499fb3a9a069b35ff352f1f6253bc0ebd03ba96 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 11 Jul 2011 16:15:12 +0200 Subject: SSL: Store x509 name entries that have no short name as their OID. Previously, x509 name entries that didn't have a shortname would all be (accidentally) stored with the tag 'UNDEF'. This commit changes things so that they are stored using the string form of their OID. Change-Id: I667306cc4f91b1ca84f29b986bc21daadeb089b6 Merge-request: 18 Reviewed-by: Peter Hartmann Reviewed-on: http://codereview.qt.nokia.com/1449 Reviewed-by: Qt Sanity Bot --- src/network/ssl/qsslcertificate.cpp | 16 ++++++++++++++-- src/network/ssl/qsslsocket_openssl_symbols.cpp | 6 ++++++ src/network/ssl/qsslsocket_openssl_symbols_p.h | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 7403590f8c..4f7c86ef4f 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -711,12 +711,24 @@ static QMap _q_mapFromX509Name(X509_NAME *name) QMap info; for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) { X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i); - const char *obj = q_OBJ_nid2sn(q_OBJ_obj2nid(q_X509_NAME_ENTRY_get_object(e))); + + int nid = q_OBJ_obj2nid(q_X509_NAME_ENTRY_get_object(e)); + const char *obj=0; + char buf[80]; + if (nid != NID_undef) { + obj = q_OBJ_nid2sn(nid); + } + else { + // This is used for unknown info so we get the OID as text + q_i2t_ASN1_OBJECT(buf,sizeof(buf),e->object); + } unsigned char *data = 0; int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e)); - info.insertMulti(QString::fromUtf8(obj), QString::fromUtf8((char*)data, size)); + info.insertMulti(QString::fromUtf8(obj ? obj : reinterpret_cast(&buf)), + QString::fromUtf8((char*)data, size)); q_CRYPTO_free(data); } + return info; } diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 18a845b312..31afab003f 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -133,6 +133,10 @@ DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return) +DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return) +DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return) + + DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) #ifdef SSLEAY_MACROS DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) @@ -688,6 +692,8 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EVP_PKEY_new) RESOLVEFUNC(EVP_PKEY_type) RESOLVEFUNC(OBJ_nid2sn) + RESOLVEFUNC(OBJ_nid2ln) + RESOLVEFUNC(i2t_ASN1_OBJECT) RESOLVEFUNC(OBJ_obj2nid) #ifdef SSLEAY_MACROS // ### verify RESOLVEFUNC(PEM_ASN1_read_bio) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 12b3890512..cd3aa07bc0 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -237,6 +237,8 @@ int q_EVP_PKEY_type(int a); EVP_PKEY *q_EVP_PKEY_new(); int q_i2d_X509(X509 *a, unsigned char **b); const char *q_OBJ_nid2sn(int a); +const char *q_OBJ_nid2ln(int a); +int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj); int q_OBJ_obj2nid(const ASN1_OBJECT *a); #ifdef SSLEAY_MACROS // ### verify -- cgit v1.2.3 From 14b56b2be40fc6290e096116edad979982eb83dd Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 11 Jul 2011 16:15:13 +0200 Subject: SSL: Make the internals of certificate name info match the externals. The internals of QSslCertificate were using QString but the API used QByteArray, this commit unifies the code. This means that we don't keep converting things. Change-Id: I29fc149a85b77e786a6e90e5154c62f713476599 Merge-request: 18 Reviewed-by: Peter Hartmann Reviewed-on: http://codereview.qt.nokia.com/1450 Reviewed-by: Qt Sanity Bot --- src/network/ssl/qsslcertificate.cpp | 34 +++++++++++++++++----------------- src/network/ssl/qsslcertificate_p.h | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 4f7c86ef4f..2e5b313d4e 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -128,7 +128,7 @@ QT_BEGIN_NAMESPACE // forward declaration -static QMap _q_mapFromX509Name(X509_NAME *name); +static QMap _q_mapFromX509Name(X509_NAME *name); /*! Constructs a QSslCertificate by reading \a format encoded data @@ -297,19 +297,19 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons return QCryptographicHash::hash(toDer(), algorithm); } -static QString _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) +static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) { - QString str; + QByteArray str; switch (info) { - case QSslCertificate::Organization: str = QLatin1String("O"); break; - case QSslCertificate::CommonName: str = QLatin1String("CN"); break; - case QSslCertificate::LocalityName: str = QLatin1String("L"); break; - case QSslCertificate::OrganizationalUnitName: str = QLatin1String("OU"); break; - case QSslCertificate::CountryName: str = QLatin1String("C"); break; - case QSslCertificate::StateOrProvinceName: str = QLatin1String("ST"); break; - case QSslCertificate::DistinguishedNameQualifier: str = QLatin1String("dnQualifier"); break; - case QSslCertificate::SerialNumber: str = QLatin1String("serialNumber"); break; - case QSslCertificate::EmailAddress: str = QLatin1String("emailAddress"); break; + case QSslCertificate::Organization: str = QByteArray("O"); break; + case QSslCertificate::CommonName: str = QByteArray("CN"); break; + case QSslCertificate::LocalityName: str = QByteArray("L"); break; + case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break; + case QSslCertificate::CountryName: str = QByteArray("C"); break; + case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break; + case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break; + case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break; + case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break; } return str; } @@ -347,7 +347,7 @@ QStringList QSslCertificate::issuerInfo(const QByteArray &tag) const d->issuerInfo = _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); - return d->issuerInfo.values(QString::fromLatin1(tag)); + return d->issuerInfo.values(tag); } /*! @@ -382,7 +382,7 @@ QStringList QSslCertificate::subjectInfo(const QByteArray &tag) const d->subjectInfo = _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); - return d->subjectInfo.values(QString::fromLatin1(tag)); + return d->subjectInfo.values(tag); } /*! @@ -706,9 +706,9 @@ QByteArray QSslCertificatePrivate::text_from_X509(X509 *x509) return result; } -static QMap _q_mapFromX509Name(X509_NAME *name) +static QMap _q_mapFromX509Name(X509_NAME *name) { - QMap info; + QMap info; for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) { X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i); @@ -724,7 +724,7 @@ static QMap _q_mapFromX509Name(X509_NAME *name) } unsigned char *data = 0; int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e)); - info.insertMulti(QString::fromUtf8(obj ? obj : reinterpret_cast(&buf)), + info.insertMulti(QByteArray(obj ? obj : reinterpret_cast(&buf)), QString::fromUtf8((char*)data, size)); q_CRYPTO_free(data); } diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index eb192968c5..fdffc7218b 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -83,8 +83,8 @@ public: QByteArray versionString; QByteArray serialNumberString; - QMap issuerInfo; - QMap subjectInfo; + QMap issuerInfo; + QMap subjectInfo; QDateTime notValidAfter; QDateTime notValidBefore; -- cgit v1.2.3 From 852d4b03f612748fb16f592dda884e9634b468cf Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 11 Jul 2011 16:15:14 +0200 Subject: SSL: Add methods to access the tags of the subject and issuer of a cert Add methods that return a list of the tags in use in a certificate issuer or subject. This means that unknown elements of these fields can be accessed. Change-Id: I588989e34f541b1d31cc9e97f5a85d1624ece1b1 Merge-request: 18 Reviewed-by: Peter Hartmann Reviewed-on: http://codereview.qt.nokia.com/1451 --- src/network/ssl/qsslcertificate.cpp | 38 +++++++++++++++++++++++++++++++++++++ src/network/ssl/qsslcertificate.h | 2 ++ 2 files changed, 40 insertions(+) (limited to 'src') diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 2e5b313d4e..9cc74c633c 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -385,6 +385,44 @@ QStringList QSslCertificate::subjectInfo(const QByteArray &tag) const return d->subjectInfo.values(tag); } +/*! + Returns a list of the tags that have values in the subject + information of this certificate. The information associated + with a given tag can be accessed using the subjectInfo() + method. Note that this list may include the OIDs for any + elements that are not known by the SSL backend. + + \sa subjectInfo() +*/ +QList QSslCertificate::subjectInfoTags() const +{ + // lazy init + if (d->subjectInfo.isEmpty() && d->x509) + d->subjectInfo = + _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); + + return d->subjectInfo.uniqueKeys(); +} + +/*! + Returns a list of the tags that have values in the issuer + information of this certificate. The information associated + with a given tag can be accessed using the issuerInfo() + method. Note that this list may include the OIDs for any + elements that are not known by the SSL backend. + + \sa subjectInfo() +*/ +QList QSslCertificate::issuerInfoTags() const +{ + // lazy init + if (d->issuerInfo.isEmpty() && d->x509) + d->issuerInfo = + _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); + + return d->issuerInfo.uniqueKeys(); +} + /*! Returns the list of alternative subject names for this certificate. The alternate subject names typically contain host diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index 8abaa3f73e..b038a6ab88 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -103,6 +103,8 @@ public: QStringList issuerInfo(const QByteArray &tag) const; QStringList subjectInfo(SubjectInfo info) const; QStringList subjectInfo(const QByteArray &tag) const; + QList subjectInfoTags() const; + QList issuerInfoTags() const; QMultiMap alternateSubjectNames() const; QDateTime effectiveDate() const; QDateTime expiryDate() const; -- cgit v1.2.3 From eab215070efb43867dd53279759b4f2c9b348567 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 11 Jul 2011 16:15:15 +0200 Subject: SSL: Move the code for extracting the name of an ASN1_OBJECT Moves the code for extracting the name of an ASN1_OBJECT to a function. We're going to need this again for implementing support for X509 extensions. Change-Id: I43276eb375b37f5fef0d981f4003220d7e7b81ba Merge-request: 18 Reviewed-by: Peter Hartmann Reviewed-on: http://codereview.qt.nokia.com/1452 Reviewed-by: Qt Sanity Bot --- src/network/ssl/qsslcertificate.cpp | 27 +++++++++++++++------------ src/network/ssl/qsslcertificate_p.h | 1 + 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 9cc74c633c..06a2071161 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -744,26 +744,29 @@ QByteArray QSslCertificatePrivate::text_from_X509(X509 *x509) return result; } +QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object) +{ + int nid = q_OBJ_obj2nid(object); + if (nid != NID_undef) + return QByteArray(q_OBJ_nid2sn(nid)); + + // This is used for unknown info so we get the OID as text + char buf[80]; + q_i2t_ASN1_OBJECT(buf, sizeof(buf), object); + + return QByteArray(buf); +} + static QMap _q_mapFromX509Name(X509_NAME *name) { QMap info; for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) { X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i); - int nid = q_OBJ_obj2nid(q_X509_NAME_ENTRY_get_object(e)); - const char *obj=0; - char buf[80]; - if (nid != NID_undef) { - obj = q_OBJ_nid2sn(nid); - } - else { - // This is used for unknown info so we get the OID as text - q_i2t_ASN1_OBJECT(buf,sizeof(buf),e->object); - } + QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e)); unsigned char *data = 0; int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e)); - info.insertMulti(QByteArray(obj ? obj : reinterpret_cast(&buf)), - QString::fromUtf8((char*)data, size)); + info.insertMulti(name, QString::fromUtf8((char*)data, size)); q_CRYPTO_free(data); } diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index fdffc7218b..3cfcef7b57 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -92,6 +92,7 @@ public: void init(const QByteArray &data, QSsl::EncodingFormat format); + static QByteArray asn1ObjectName(ASN1_OBJECT *object); static QByteArray QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format); static QByteArray text_from_X509(X509 *x509); static QSslCertificate QSslCertificate_from_X509(X509 *x509); -- cgit v1.2.3 From d1f080138a0bfaf845d051867c919bcb0e95c739 Mon Sep 17 00:00:00 2001 From: Jedrzej Nowacki Date: Fri, 10 Jun 2011 11:28:05 +0200 Subject: Cleanup reference counting in QIcon class It is better to use QSharedData and QExplicitlySharedDataPointer then doing manual ref counting. Change-Id: Icbb06d92102bcc906291238c5895a05e8d0e6de1 Reviewed-on: http://codereview.qt.nokia.com/1438 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/gui/image/qicon.cpp | 18 +++--------------- src/gui/image/qicon.h | 4 ++-- src/gui/image/qicon_p.h | 3 +-- 3 files changed, 6 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index e24087c3c5..7cf749fabc 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -116,7 +116,7 @@ static void qt_cleanup_icon_cache() } QIconPrivate::QIconPrivate() - : engine(0), ref(1), + : engine(0), serialNum(serialNumCounter.fetchAndAddRelaxed(1)), detach_no(0), engine_version(2), @@ -536,10 +536,7 @@ QIcon::QIcon(const QPixmap &pixmap) */ QIcon::QIcon(const QIcon &other) :d(other.d) -{ - if (d) - d->ref.ref(); -} +{} /*! Constructs an icon from the file with the given \a fileName. The @@ -593,10 +590,7 @@ QIcon::QIcon(QIconEngineV2 *engine) Destroys the icon. */ QIcon::~QIcon() -{ - if (d && !d->ref.deref()) - delete d; -} +{} /*! Assigns the \a other icon to this icon and returns a reference to @@ -604,10 +598,6 @@ QIcon::~QIcon() */ QIcon &QIcon::operator=(const QIcon &other) { - if (other.d) - other.d->ref.ref(); - if (d && !d->ref.deref()) - delete d; d = other.d; return *this; } @@ -775,8 +765,6 @@ void QIcon::detach() x->v1RefCount->ref(); } x->engine_version = d->engine_version; - if (!d->ref.deref()) - delete d; d = x; } ++d->detach_no; diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 98bb2f8393..eb14384f78 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -132,14 +132,14 @@ public: Q_DUMMY_COMPARISON_OPERATOR(QIcon) private: - QIconPrivate *d; + QExplicitlySharedDataPointer d; #if !defined(QT_NO_DATASTREAM) friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QIcon &); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QIcon &); #endif public: - typedef QIconPrivate * DataPtr; + typedef QExplicitlySharedDataPointer DataPtr; inline DataPtr &data_ptr() { return d; } }; diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index 2708fd3f45..c5b4bb0ba7 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -63,7 +63,7 @@ #ifndef QT_NO_ICON QT_BEGIN_NAMESPACE -class QIconPrivate +class QIconPrivate : public QSharedData { public: QIconPrivate(); @@ -81,7 +81,6 @@ public: QIconEngine *engine; - QAtomicInt ref; int serialNum; int detach_no; int engine_version; -- cgit v1.2.3 From 12d9436522c13f5317617670e20991ef647f211a Mon Sep 17 00:00:00 2001 From: Jedrzej Nowacki Date: Fri, 10 Jun 2011 09:06:32 +0200 Subject: Cleanup reference counting in internal::Base class (qtconcurrent) It is better to use QSharedData and QExplicitlySharedDataPointer then doing manual ref counting. Change-Id: I5674046141701bd48a53415ab96fcb6b538e79e6 Reviewed-on: http://codereview.qt.nokia.com/1440 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/concurrent/qtconcurrentexception.cpp | 22 +++++----------------- src/corelib/concurrent/qtconcurrentexception.h | 3 ++- 2 files changed, 7 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/corelib/concurrent/qtconcurrentexception.cpp b/src/corelib/concurrent/qtconcurrentexception.cpp index 933ad3c264..237152c0d3 100644 --- a/src/corelib/concurrent/qtconcurrentexception.cpp +++ b/src/corelib/concurrent/qtconcurrentexception.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qtconcurrentexception.h" +#include "QtCore/qshareddata.h" #ifndef QT_NO_QFUTURE #ifndef QT_NO_EXCEPTIONS @@ -141,15 +142,14 @@ Exception *UnhandledException::clone() const namespace internal { -class Base +class Base : public QSharedData { public: Base(Exception *exception) - : exception(exception), refCount(1), hasThrown(false) { } + : exception(exception), hasThrown(false) { } ~Base() { delete exception; } Exception *exception; - QAtomicInt refCount; bool hasThrown; }; @@ -158,27 +158,15 @@ ExceptionHolder::ExceptionHolder(Exception *exception) ExceptionHolder::ExceptionHolder(const ExceptionHolder &other) : base(other.base) -{ - base->refCount.ref(); -} +{} void ExceptionHolder::operator=(const ExceptionHolder &other) { - if (base == other.base) - return; - - if (base->refCount.deref() == false) - delete base; - base = other.base; - base->refCount.ref(); } ExceptionHolder::~ExceptionHolder() -{ - if (base->refCount.deref() == 0) - delete base; -} +{} Exception *ExceptionHolder::exception() const { diff --git a/src/corelib/concurrent/qtconcurrentexception.h b/src/corelib/concurrent/qtconcurrentexception.h index b58b3ba23a..1c100a5206 100644 --- a/src/corelib/concurrent/qtconcurrentexception.h +++ b/src/corelib/concurrent/qtconcurrentexception.h @@ -47,6 +47,7 @@ #ifndef QT_NO_QFUTURE #include +#include #ifndef QT_NO_EXCEPTIONS # include @@ -87,7 +88,7 @@ public: void operator=(const ExceptionHolder &other); ~ExceptionHolder(); Exception *exception() const; - Base *base; + QExplicitlySharedDataPointer base; }; class Q_CORE_EXPORT ExceptionStore -- cgit v1.2.3 From 94e110ca5f70f61bb7f6a99be121e5d78670a22a Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 11 Jul 2011 16:39:14 +0200 Subject: QSslCertificate: rename "tag" to "attribute", as in the RFC RFC 2459 "Internet X.509 Public Key Infrastructure" uses the word "attribute" for fields in a certificate like common name, organization etc. Change-Id: I51e595acbe3e146acf81af21cf48e554fa9490e4 Reviewed-on: http://codereview.qt.nokia.com/1453 Reviewed-by: Qt Sanity Bot Reviewed-by: Martin Petersson --- src/network/ssl/qsslcertificate.cpp | 28 ++++++++++++++-------------- src/network/ssl/qsslcertificate.h | 8 ++++---- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 06a2071161..839a253b99 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -334,20 +334,20 @@ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const } /*! - Returns the issuer information for \a tag from the certificate, - or an empty string if there is no information for \a tag in the + Returns the issuer information for \a attribute from the certificate, + or an empty string if there is no information for \a attribute in the certificate. \sa subjectInfo() */ -QStringList QSslCertificate::issuerInfo(const QByteArray &tag) const +QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const { // lazy init if (d->issuerInfo.isEmpty() && d->x509) d->issuerInfo = _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); - return d->issuerInfo.values(tag); + return d->issuerInfo.values(attribute); } /*! @@ -370,31 +370,31 @@ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const } /*! - Returns the subject information for \a tag, or an empty string if - there is no information for \a tag in the certificate. + Returns the subject information for \a attribute, or an empty string if + there is no information for \a attribute in the certificate. \sa issuerInfo() */ -QStringList QSslCertificate::subjectInfo(const QByteArray &tag) const +QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const { // lazy init if (d->subjectInfo.isEmpty() && d->x509) d->subjectInfo = _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); - return d->subjectInfo.values(tag); + return d->subjectInfo.values(attribute); } /*! - Returns a list of the tags that have values in the subject + Returns a list of the attributes that have values in the subject information of this certificate. The information associated - with a given tag can be accessed using the subjectInfo() + with a given attribute can be accessed using the subjectInfo() method. Note that this list may include the OIDs for any elements that are not known by the SSL backend. \sa subjectInfo() */ -QList QSslCertificate::subjectInfoTags() const +QList QSslCertificate::subjectInfoAttributes() const { // lazy init if (d->subjectInfo.isEmpty() && d->x509) @@ -405,15 +405,15 @@ QList QSslCertificate::subjectInfoTags() const } /*! - Returns a list of the tags that have values in the issuer + Returns a list of the attributes that have values in the issuer information of this certificate. The information associated - with a given tag can be accessed using the issuerInfo() + with a given attribute can be accessed using the issuerInfo() method. Note that this list may include the OIDs for any elements that are not known by the SSL backend. \sa subjectInfo() */ -QList QSslCertificate::issuerInfoTags() const +QList QSslCertificate::issuerInfoAttributes() const { // lazy init if (d->issuerInfo.isEmpty() && d->x509) diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index b038a6ab88..4de84dd4ba 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -100,11 +100,11 @@ public: QByteArray serialNumber() const; QByteArray digest(QCryptographicHash::Algorithm algorithm = QCryptographicHash::Md5) const; QStringList issuerInfo(SubjectInfo info) const; - QStringList issuerInfo(const QByteArray &tag) const; + QStringList issuerInfo(const QByteArray &attribute) const; QStringList subjectInfo(SubjectInfo info) const; - QStringList subjectInfo(const QByteArray &tag) const; - QList subjectInfoTags() const; - QList issuerInfoTags() const; + QStringList subjectInfo(const QByteArray &attribute) const; + QList subjectInfoAttributes() const; + QList issuerInfoAttributes() const; QMultiMap alternateSubjectNames() const; QDateTime effectiveDate() const; QDateTime expiryDate() const; -- cgit v1.2.3 From 6618dd877f83be56d140882a2f6c3fa5a985c2d2 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 8 Jun 2011 11:43:27 +0200 Subject: Introduce QT_DEPRECATED_SINCE To be used to versionize deprecated symbols Symbols deprecated in Qt 5.0 need to be inlined Change-Id: I696a834c25b7e86acf14ae081ea91ef993a5b19e Reviewed-on: http://codereview.qt.nokia.com/431 Reviewed-by: Qt Sanity Bot Reviewed-by: Lars Knoll --- src/corelib/global/qglobal.cpp | 15 +++++++++++++++ src/corelib/global/qglobal.h | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index ca8b30fc00..bbc9a15e74 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1642,6 +1642,21 @@ bool qSharedBuild() \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS */ +/*! + \macro QT_DISABLE_DEPRECATED_BEFORE + \relates + + This macro can be defined in the project file to disable functions deprecated in + a specified version of Qt or any earlier version. The default version number is 5.0, + meaning that functions deprecated in or before Qt 5.0 will not be included. + + Examples: + When using a future release of Qt 5, set QT_DISABLE_DEPRECATED_BEFORE=0x050100 to + disable functions deprecated in Qt 5.1 and earlier. In any release, set + QT_DISABLE_DEPRECATED_BEFORE=0x000000 to enable any functions, including the ones + deprecated in Qt 5.0 + */ + #if defined(QT_BUILD_QMAKE) // needed to bootstrap qmake static const unsigned int qt_one = 1; diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 15145ced07..1358ea62df 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -54,6 +54,23 @@ */ #define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) +#ifndef QT_DISABLE_DEPRECATED_BEFORE +#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0) +#endif + +/* + QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than + the deprecation point specified. + + Use it to specify from which version of Qt a function or class has been deprecated + + Example: + #if QT_DEPRECATED_SINCE(5,1) + QT_DEPRECATED void deprecatedFunction(); //function deprecated sine Qt 5.1 + #endif + */ +#define QT_DEPRECATED_SINCE(major, minor) (QT_VERSION_CHECK(major, minor, 0) > QT_DISABLE_DEPRECATED_BEFORE) + #define QT_PACKAGEDATE_STR "YYYY-MM-DD" #define QT_PACKAGE_TAG "" -- cgit v1.2.3 From 82454b6014a7ee0b048b4db8d64a21de849d4ab9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 12 Jul 2011 09:08:55 +0200 Subject: remove unneeded cast operator on QConstStringData Change-Id: Ib5f090cd6c716e1d936894be206b78629e70137b Reviewed-on: http://codereview.qt.nokia.com/1487 Reviewed-by: Qt Sanity Bot Reviewed-by: Olivier Goffart --- src/corelib/tools/qstring.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 34f160e782..27948e04ea 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -101,7 +101,6 @@ template struct QConstStringData { const QStringData str; const char16_t data[n]; - operator const QStringData &() const { return str; } }; #define QT_QSTRING_UNICODE_MARKER u"" @@ -111,7 +110,6 @@ template struct QConstStringData { const QStringData str; const wchar_t data[n]; - operator const QStringData &() const { return str; } }; #define QT_QSTRING_UNICODE_MARKER L"" @@ -120,7 +118,6 @@ template struct QConstStringData { const QStringData str; const ushort data[n]; - operator const QStringData &() const { return str; } }; #endif -- cgit v1.2.3