diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index 7c766dff31ec64c8d9b1b834ddf26fa5f596fc6e..5cd7ed519ce9210042b5fc4cffdf997d76fff0ec 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -56,6 +56,7 @@ int qtGhVersion = QT_VERSION; #ifdef QT_GUI_LIB +# include <QtGui/QWidget> # include <QtGui/QPixmap> # include <QtGui/QImage> #endif @@ -2186,6 +2187,44 @@ static void qDumpQVector(QDumper &d) d.disarm(); } +static void qDumpQWeakPointer(QDumper &d) +{ + const int v = sizeof(void *); + const void *value = deref(addOffset(d.data, v)); + + if (isSimpleType(d.innertype)) + qDumpInnerValueHelper(d, d.innertype, value); + else + P(d, "value", ""); + P(d, "valuedisabled", "true"); + P(d, "numchild", 1); + if (d.dumpChildren) { + d << ",children=["; + d.beginHash(); + P(d, "name", "data"); + qDumpInnerValue(d, d.innertype, value); + d.endHash(); + d.beginHash(); + const void *weak = addOffset(deref(d.data), v); + P(d, "name", "weakref"); + P(d, "value", *static_cast<const int *>(weak)); + P(d, "type", "int"); + P(d, "addr", weak); + P(d, "numchild", "0"); + d.endHash(); + d.beginHash(); + const void *strong = addOffset(weak, sizeof(int)); + P(d, "name", "strongref"); + P(d, "value", *static_cast<const int *>(strong)); + P(d, "type", "int"); + P(d, "addr", strong); + P(d, "numchild", "0"); + d.endHash(); + d << "]"; + } + d.disarm(); +} + static void qDumpStdList(QDumper &d) { const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data); @@ -2558,16 +2597,6 @@ static void handleProtocolVersion2and3(QDumper & d) else if (isEqual(type, "QStringList")) qDumpQStringList(d); break; - case 'T': - if (isEqual(type, "QTextCodec")) - qDumpQTextCodec(d); - break; - case 'V': - if (isEqual(type, "QVariant")) - qDumpQVariant(d); - else if (isEqual(type, "QVector")) - qDumpQVector(d); - break; case 's': if (isEqual(type, "wstring")) qDumpStdWString(d); @@ -2588,6 +2617,19 @@ static void handleProtocolVersion2and3(QDumper & d) else if (isEqual(type, "std::wstring")) qDumpStdWString(d); break; + case 'T': + if (isEqual(type, "QTextCodec")) + qDumpQTextCodec(d); + break; + case 'V': + if (isEqual(type, "QVariant")) + qDumpQVariant(d); + else if (isEqual(type, "QVector")) + qDumpQVector(d); + break; + case 'W': + if (isEqual(type, "QWeakPointer")) + qDumpQWeakPointer(d); } if (!d.success) @@ -2663,6 +2705,7 @@ void *qDumpObjectData440( "\""NS"QTextCodec\"," "\""NS"QVariant\"," "\""NS"QVector\"," + "\""NS"QWeakPointer\"," "\""NS"QWidget\"," #ifdef Q_OS_WIN "\"basic_string\"," @@ -2685,7 +2728,25 @@ void *qDumpObjectData440( "\"" << ((QT_VERSION >> 16) & 255) << "\"," "\"" << ((QT_VERSION >> 8) & 255) << "\"," "\"" << ((QT_VERSION) & 255) << "\"]"; - d << ",namespace=\""NS"\""; + d << ",namespace=\""NS"\","; +// Dump out size information + d << "sizes={"; + d << "int=\"" << sizeof(int) << "\"," + << "char*=\"" << sizeof(char*) << "\"," + << ""NS"QString=\"" << sizeof(QString) << "\"," + << ""NS"QStringList=\"" << sizeof(QStringList) << "\"," + << ""NS"QObject=\"" << sizeof(QObject) << "\"," +#ifdef QT_GUI_LIB + << ""NS"QWidget=\"" << sizeof(QWidget)<< "\"," +#endif +#ifdef Q_OS_WIN + << "string=\"" << sizeof(std::string) << "\"," + << "wstring=\"" << sizeof(std::wstring) << "\"," +#endif + << "std::string=\"" << sizeof(std::string) << "\"," + << "std::wstring=\"" << sizeof(std::wstring) << "\"," + << "std::allocator=\"" << sizeof(std::allocator<int>) + << "\"}"; d.disarm(); } diff --git a/src/libs/utils/qstringbuilder.cpp b/src/libs/utils/qstringbuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3925e56b5e62bc0c81c554c17b68b67ff476ad9 --- /dev/null +++ b/src/libs/utils/qstringbuilder.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstringbuilder.h" + +/*! + \class QLatin1Literal + \reentrant + + \brief The QLatin1Literal class provides a thin wrapper of string literal + used in source codes. + + 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. + + Contrary to \c QLatin1String, a \c QLatin1Literal can retrieve its size + int \i{O(1)}. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + + \sa QStringBuilder, QLatin1String, QString + +*/ + +/*! \fn QLatin1Literal::QLatin1Literal(const char(&literal)[]) + + The only constructor of the class. +*/ + +/*! \fn int QLatin1Literal::size() const + + Returns the number of characters in the literal \i{not} including + the trailing NUL char. +*/ + +/*! \fn char *QLatin1Literal::size() const + + Returns a pointer to the first character of the string literal. + The string literal is terminated by a NUL character. +*/ + +/*! \fn QLatin1Literal::operator QString() const + + Converts the \c QLatin1Literal into a \c QString object. +*/ + + +/*! + \class QStringBuilderPair + \reentrant + + \brief QStringBuilderPair is a helper class template for building + QStringBuilder objects wrapping two smaller QStringBuilder object. +*/ + + +/*! + \class QStringBuilder + \reentrant + + \brief QStringBuilder is a template class providing a facility to build + up QStrings from smaller chunks. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + + When creating strings from smaller chunks, typically \c QString::operator+() + is used, resulting \i{n - 1} reallocations when operating on \i{n} chunks. + + QStringBuilder uses expression + templates to collect the individual parts, compute the total size, + allocate memory for the resulting QString object, and copy the contents + of the chunks into the result. + + Using \c QStringBuilder::operator%() yield generally better performance then + using \c QString::operator+() on the same chunks if there are three or + more of them, and equal performance otherwise. + + \sa QLatin1Literal, QString +*/ + +/* !fn template <class A, class B> QStringBuilder< QStringBuilderPair<A, B> > operator%(const A &a, const B &b) + + Creates a helper object containing both parameters. + + This is the main function to build up +*/ diff --git a/src/libs/utils/qstringbuilder.h b/src/libs/utils/qstringbuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..d9a5d9132cfb7d79628fbe463cc7e8bea9a3fcaa --- /dev/null +++ b/src/libs/utils/qstringbuilder.h @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTRINGBUILDER_H +#define QSTRINGBUILDER_H + +#include <QtCore/qstring.h> + +#include <string.h> + +class QLatin1Literal +{ +public: + template <int N> + QLatin1Literal(const char (&str)[N]) : m_size(N - 1), m_data(str) {} + + int size() const { return m_size; } + const char *data() const { return m_data; } + + void append(QChar *&out) const + { + const char *s = m_data; + for (int i = m_size; --i >= 0;) + *out++ = *s++; + } + + operator QString() const + { + QString s; + s.resize(m_size); + QChar *d = s.data(); + append(d); + return s; + } + +private: + const int m_size; + const char *m_data; +}; + +template <class A> +class QStringBuilder : public A +{ +public: + QStringBuilder(A a_) : A(a_) {} + + operator QString() const + { + QString s; + s.resize(this->size()); + QChar *d = s.data(); + this->append(d); + return s; + } + +}; + +template <> +class QStringBuilder<QString> +{ +public: + QStringBuilder(const QString &a_) : a(&a_) {} + + inline int size() const { return a->size(); } + + inline void append(QChar *&out) const + { + const int n = a->size(); + memcpy(out, (char*)a->constData(), sizeof(QChar) * n); + out += n; + } + + inline operator QString() const { return *a; } + +private: + const QString *a; +}; + + +template <> +class QStringBuilder<char> +{ +public: + QStringBuilder(char c_) : c(c_) {} + + inline int size() const { return 1; } + inline void append(QChar *&out) const { *out++ = QLatin1Char(c); } + +private: + const char c; +}; + + + +template <class A, class B> +class QStringBuilderPair +{ +public: + QStringBuilderPair(A a_, B b_) : a(a_), b(b_) {} + inline int size() const { return a.size() + b.size(); } + inline void append(QChar *&out) const { a.append(out); b.append(out); } +private: + A a; + B b; +}; + + +template <class A, class B> +QStringBuilder< QStringBuilderPair<A, B> > +operator%(const A &a, const B &b) +{ + return QStringBuilderPair<A, B> (a, b); +} + + +// QString related specializations + +template <class A> +inline QStringBuilder< QStringBuilderPair<A, QStringBuilder<QString> > > +operator%(const A &a, const QString &b) +{ + return QStringBuilderPair<A, QStringBuilder<QString> > (a, b); +} + +template <class B> +inline QStringBuilder< QStringBuilderPair<QStringBuilder<QString>, B> > +operator%(const QString &a, const B &b) +{ + return QStringBuilderPair<QStringBuilder<QString>, B> (a, b); +} + +inline QStringBuilder< + QStringBuilderPair<QStringBuilder<QString>, QStringBuilder<QString> > +> +operator%(const QString &a, const QString &b) +{ + return QStringBuilderPair< QStringBuilder<QString>, + QStringBuilder<QString> > (a, b); +} + +// char related specializations + +template <class A> +inline QStringBuilder< QStringBuilderPair<A, QStringBuilder<char> > > +operator%(const A &a, char b) +{ + return QStringBuilderPair<A, QStringBuilder<char> > (a, b); +} + +template <class B> +inline QStringBuilder< QStringBuilderPair<QStringBuilder<char>, B> > +operator%(char a, const B &b) +{ + return QStringBuilderPair<QStringBuilder<QString>, B> (a, b); +} + +inline QStringBuilder< + QStringBuilderPair<QStringBuilder<QString>, QStringBuilder<char> > +> +operator%(const QString &a, char b) +{ + return QStringBuilderPair< + QStringBuilder<QString>, QStringBuilder<char> + > (a, b); +} + + +#endif // QSTRINGBUILDER_H diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp index 1357eb99d6f6abeba672e0ac3780f243b3932779..3f4ffdab8fd98e8df8241c96408d194109c22fcd 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp +++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp @@ -181,7 +181,6 @@ void CdbDumperHelper::reset(const QString &library, bool enabled) m_helper.clear(); m_inBufferAddress = m_outBufferAddress = 0; m_inBufferSize = m_outBufferSize = 0; - m_typeSizeCache.clear(); m_failedTypes.clear(); clearBuffer(); } @@ -405,7 +404,9 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool // Check failure cache and supported types if (m_failedTypes.contains(wd.type)) return DumpNotHandled; - const QtDumperHelper::TypeData td = m_helper.typeData(wd.type); + const QtDumperHelper::TypeData td = m_helper.typeData(wd.type); + if (loadDebug) + qDebug() << wd.type << td; if (td.type == QtDumperHelper::UnknownType) return DumpNotHandled; @@ -448,10 +449,11 @@ CdbDumperHelper::DumpExecuteResult int size; ep.truncate(ep.lastIndexOf(QLatin1Char(')'))); ep.remove(0, ep.indexOf(QLatin1Char('(')) + 1); - if (!getTypeSize(ep, &size, errorMessage)) - return DumpExecuteSizeFailed; + const bool sizeOk = getTypeSize(ep, &size, errorMessage); if (loadDebug) - qDebug() << "Size" << size << ep; + qDebug() << "Size" << sizeOk << size << ep; + if (!sizeOk) + return DumpExecuteSizeFailed; ep = QString::number(size); } } @@ -461,7 +463,7 @@ CdbDumperHelper::DumpExecuteResult << "(2,0," << wd.addr << ',' << (dumpChildren ? 1 : 0) << ',' << extraParameters.join(QString(QLatin1Char(','))) << ')'; if (loadDebug) - qDebug() << "Query: " << wd.toString() << "\nwith: " << callCmd; + qDebug() << "Query: " << wd.toString() << "\nwith: " << callCmd << '\n'; const char *outputData; if (!callDumper(callCmd, inBuffer, &outputData, errorMessage)) return DumpExecuteCallFailed; @@ -486,11 +488,6 @@ bool CdbDumperHelper::getTypeSize(const QString &typeNameIn, int *size, QString if (loadDebug > 1) qDebug() << Q_FUNC_INFO << typeNameIn; // Look up cache - const TypeSizeCache::const_iterator it = m_typeSizeCache.constFind(typeNameIn); - if (it != m_typeSizeCache.constEnd()) { - *size = it.value(); - return true; - } QString typeName = typeNameIn; simplifySizeExpression(&typeName); // "std::" types sometimes only work without namespace. @@ -511,8 +508,9 @@ bool CdbDumperHelper::getTypeSize(const QString &typeNameIn, int *size, QString break; success = true; } while (false); + // Cache in dumper helper if (success) - m_typeSizeCache.insert(typeName, *size); + m_helper.addSize(typeName, *size); return success; } diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.h b/src/plugins/debugger/cdb/cdbdumperhelper.h index 2f576b196ef978ce5447b81db71e71c0db162bd8..b9ec2bccccbbf8248a94e833bc5a30b3b9e8cf18 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.h +++ b/src/plugins/debugger/cdb/cdbdumperhelper.h @@ -119,8 +119,6 @@ private: unsigned long m_outBufferSize; char *m_buffer; - typedef QMap<QString, int> TypeSizeCache; - TypeSizeCache m_typeSizeCache; QStringList m_failedTypes; QtDumperHelper m_helper; diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index da1fead265e2435cbd72cd65d9e1d2be6c436fc0..d391907adca77a109bdabbce9d738669d884905d 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -3047,11 +3047,10 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) //int protocol = isDisplayedIName(data.iname) ? 3 : 2; QString addr; - if (data.addr.startsWith(QLatin1String("0x"))) { + if (data.addr.startsWith(QLatin1String("0x"))) addr = QLatin1String("(void*)") + data.addr; - } else { + else addr = QLatin1String("&(") + data.exp + QLatin1Char(')'); - } sendWatchParameters(params); @@ -3061,8 +3060,6 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) <<',' << addr << ',' << (dumpChildren ? "1" : "0") << ',' << extraArgs.join(QString(QLatin1Char(','))) << ')'; - qDebug() << "CMD: " << cmd; - QVariant var; var.setValue(data); sendSynchronizedCommand(cmd, WatchDebuggingHelperValue1, var); @@ -3344,7 +3341,7 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record) q->showStatusMessage(tr("%1 custom dumpers found.") .arg(m_dumperHelper.typeCount())); } - qDebug() << m_dumperHelper.toString(true); + //qDebug() << m_dumperHelper.toString(true); //qDebug() << "DATA DUMPERS AVAILABLE" << m_availableSimpleDebuggingHelpers; } diff --git a/src/plugins/debugger/scriptengine.cpp b/src/plugins/debugger/scriptengine.cpp index a0feae918268afa79ab2636700184907e70842d9..76451774c71a42a731536538270645c174f081a9 100644 --- a/src/plugins/debugger/scriptengine.cpp +++ b/src/plugins/debugger/scriptengine.cpp @@ -38,6 +38,7 @@ #include "registerhandler.h" #include "stackhandler.h" #include "watchhandler.h" +#include "watchutils.h" #include "moduleshandler.h" #include <utils/qtcassert.h> @@ -422,28 +423,6 @@ static WatchData m_toolTip; static QPoint m_toolTipPos; static QHash<QString, WatchData> m_toolTipCache; -static bool hasLetterOrNumber(const QString &exp) -{ - for (int i = exp.size(); --i >= 0; ) - if (exp[i].isLetterOrNumber()) - return true; - return false; -} - -static bool hasSideEffects(const QString &exp) -{ - // FIXME: complete? - return exp.contains("-=") - || exp.contains("+=") - || exp.contains("/=") - || exp.contains("*=") - || exp.contains("&=") - || exp.contains("|=") - || exp.contains("^=") - || exp.contains("--") - || exp.contains("++"); -} - void ScriptEngine::setToolTipExpression(const QPoint &pos, const QString &exp0) { Q_UNUSED(pos); diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index c1150c2ad8f15598a3180500263bf8307d0b1066..5be973677e19338d6fe9360b8768f6d773005b72 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -166,8 +166,10 @@ bool isPointerType(const QString &type) bool isAccessSpecifier(const QString &str) { - static const QStringList items = - QStringList() << QLatin1String("private") << QLatin1String("protected") << QLatin1String("public"); + static const QStringList items = QStringList() + << QLatin1String("private") + << QLatin1String("protected") + << QLatin1String("public"); return items.contains(str); } @@ -326,28 +328,28 @@ static QString quoteUnprintableLatin1(const QByteArray &ba) return res; } -QString decodeData(const QByteArray &baIn, int encoding) +QString decodeData(const QByteArray &ba, int encoding) { switch (encoding) { case 0: // unencoded 8 bit data - return quoteUnprintableLatin1(baIn); + return quoteUnprintableLatin1(ba); case 1: { // base64 encoded 8 bit data, used for QByteArray const QChar doubleQuote(QLatin1Char('"')); QString rc = doubleQuote; - rc += quoteUnprintableLatin1(QByteArray::fromBase64(baIn)); + rc += quoteUnprintableLatin1(QByteArray::fromBase64(ba)); rc += doubleQuote; return rc; } case 2: { // base64 encoded 16 bit data, used for QString const QChar doubleQuote(QLatin1Char('"')); - const QByteArray ba = QByteArray::fromBase64(baIn); + const QByteArray ba = QByteArray::fromBase64(ba); QString rc = doubleQuote; rc += QString::fromUtf16(reinterpret_cast<const ushort *>(ba.data()), ba.size() / 2); rc += doubleQuote; return rc; } case 3: { // base64 encoded 32 bit data - const QByteArray ba = QByteArray::fromBase64(baIn); + const QByteArray ba = QByteArray::fromBase64(ba); const QChar doubleQuote(QLatin1Char('"')); QString rc = doubleQuote; rc += QString::fromUcs4(reinterpret_cast<const uint *>(ba.data()), ba.size() / 4); @@ -355,7 +357,7 @@ QString decodeData(const QByteArray &baIn, int encoding) return rc; } case 4: { // base64 encoded 16 bit data, without quotes (see 2) - const QByteArray ba = QByteArray::fromBase64(baIn); + const QByteArray ba = QByteArray::fromBase64(ba); return QString::fromUtf16(reinterpret_cast<const ushort *>(ba.data()), ba.size() / 2); } } @@ -374,7 +376,6 @@ QtDumperResult::QtDumperResult() : valuedisabled(false), childCount(0), internal(false) - { } @@ -470,6 +471,10 @@ void QtDumperHelper::TypeData::clear() // ----------------- QtDumperHelper QtDumperHelper::QtDumperHelper() : + m_stdAllocatorPrefix(QLatin1String("std::allocator")), + m_intSize(0), + m_pointerSize(0), + m_stdAllocatorSize(0), m_qtVersion(0) { } @@ -479,6 +484,10 @@ void QtDumperHelper::clear() m_nameTypeMap.clear(); m_qtVersion = 0; m_qtNamespace.clear(); + m_sizeCache.clear(); + m_intSize = 0; + m_pointerSize = 0; + m_stdAllocatorSize = 0; } static inline void formatQtVersion(int v, QTextStream &str) @@ -498,6 +507,12 @@ QString QtDumperHelper::toString(bool debug) const for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) { str <<",[" << it.key() << ',' << it.value() << ']'; } + str << "Sizes: intsize=" << m_intSize << " pointer size=" << m_pointerSize + << " allocatorsize=" << m_stdAllocatorSize; + const SizeCache::const_iterator scend = m_sizeCache.constEnd(); + for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) { + str << ' ' << it.key() << '=' << it.value(); + } return rc; } const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace; @@ -584,7 +599,6 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s) return UnknownType; } - bool QtDumperHelper::needsExpressionSyntax(Type t) { switch (t) { @@ -600,7 +614,7 @@ bool QtDumperHelper::needsExpressionSyntax(Type t) return true; default: break; - } + } return false; } @@ -638,9 +652,8 @@ void QtDumperHelper::parseQueryTypes(const QStringList &l, Debugger debugger) const Type t = specialType(l.at(i)); if (t != UnknownType) { // Exclude types that require expression syntax for CDB - if (debugger == GdbDebugger || !needsExpressionSyntax(t)) { + if (debugger == GdbDebugger || !needsExpressionSyntax(t)) m_nameTypeMap.insert(l.at(i), t); - } } else { m_nameTypeMap.insert(l.at(i), SupportedType); } @@ -654,7 +667,8 @@ void QtDumperHelper::parseQueryTypes(const QStringList &l, Debugger debugger) * value="dABoAHIAZQBlAA==",valueencoded="2"}]" * Default implementation can be used for debugging purposes. */ -class DumperParser { +class DumperParser +{ public: explicit DumperParser(const char *s) : m_s(s) {} bool run(); @@ -824,6 +838,7 @@ bool DumperParser::handleValue(const char *k, int size) class QueryDumperParser : public DumperParser { public: + typedef QPair<QString, int> SizeEntry; explicit QueryDumperParser(const char *s); struct Data { @@ -831,20 +846,23 @@ public: QString qtNameSpace; QString qtVersion; QStringList types; + QList<SizeEntry> sizes; }; inline Data data() const { return m_data; } protected: virtual bool handleKeyword(const char *k, int size); - virtual bool handleListStart(); + virtual bool handleListStart(); virtual bool handleListEnd(); + virtual bool handleHashEnd(); virtual bool handleValue(const char *k, int size); private: - enum Mode { None, ExpectingDumpers, ExpectingVersion, ExpectingNameSpace }; + enum Mode { None, ExpectingDumpers, ExpectingVersion, ExpectingNameSpace, ExpectingSizes }; Mode m_mode; Data m_data; + QString m_lastSizeType; }; QueryDumperParser::QueryDumperParser(const char *s) : @@ -854,7 +872,11 @@ QueryDumperParser::QueryDumperParser(const char *s) : } bool QueryDumperParser::handleKeyword(const char *k, int size) -{ +{ + if (m_mode == ExpectingSizes) { + m_lastSizeType = QString::fromLatin1(k, size); + return true; + } if (!qstrncmp(k, "dumpers", size)) { m_mode = ExpectingDumpers; return true; @@ -867,6 +889,10 @@ bool QueryDumperParser::handleKeyword(const char *k, int size) m_mode = ExpectingNameSpace; return true; } + if (!qstrncmp(k, "sizes", size)) { + m_mode = ExpectingSizes; + return true; + } qWarning("%s Unexpected keyword %s.\n", Q_FUNC_INFO, QByteArray(k, size).constData()); return false; } @@ -882,15 +908,21 @@ bool QueryDumperParser::handleListEnd() return true; } +bool QueryDumperParser::handleHashEnd() +{ + m_mode = None; // Size hash + return true; +} + bool QueryDumperParser::handleValue(const char *k, int size) { switch (m_mode) { - case None: + case None: return false; - case ExpectingDumpers: + case ExpectingDumpers: m_data.types.push_back(QString::fromLatin1(k, size)); break; - case ExpectingNameSpace: + case ExpectingNameSpace: m_data.qtNameSpace = QString::fromLatin1(k, size); break; case ExpectingVersion: // ["4","1","5"] @@ -898,6 +930,9 @@ bool QueryDumperParser::handleValue(const char *k, int size) m_data.qtVersion += QLatin1Char('.'); m_data.qtVersion += QString::fromLatin1(k, size); break; + case ExpectingSizes: + m_data.sizes.push_back(SizeEntry(m_lastSizeType, QString::fromLatin1(k, size).toInt())); + break; } return true; } @@ -905,7 +940,6 @@ bool QueryDumperParser::handleValue(const char *k, int size) // parse a query bool QtDumperHelper::parseQuery(const char *data, Debugger debugger) { - QueryDumperParser parser(data); if (!parser.run()) return false; @@ -913,9 +947,39 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger) m_qtNamespace = parser.data().qtNameSpace; setQtVersion(parser.data().qtVersion); parseQueryTypes(parser.data().types, debugger); + foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes) + addSize(se.first, se.second); return true; } +void QtDumperHelper::addSize(const QString &name, int size) +{ + // Special interest cases + do { + if (name == QLatin1String("char*")) { + m_pointerSize = size; + break; + } + if (name == QLatin1String("int")) { + m_intSize = size; + break; + } + if (name.startsWith(m_stdAllocatorPrefix)) { + m_stdAllocatorSize = size; + break; + } + if (name == QLatin1String("std::string")) { + m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char>>"), size); + break; + } + if (name == QLatin1String("std::wstring")) { + m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsignedshort>,std::allocator<unsignedshort> >"), size); + break; + } + } while (false); + m_sizeCache.insert(name, size); +} + QtDumperHelper::Type QtDumperHelper::type(const QString &typeName) const { const QtDumperHelper::TypeData td = typeData(typeName); @@ -941,9 +1005,26 @@ QtDumperHelper::TypeData QtDumperHelper::typeData(const QString &typeName) const return td; } +// Format an expression to have the debugger query the +// size. Use size cache if possible +QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName, + Debugger /* debugger */) const +{ + // Look up fixed types + if (m_pointerSize && isPointerType(typeName)) + return QString::number(m_pointerSize); + if (m_stdAllocatorSize && typeName.startsWith(m_stdAllocatorPrefix)) + return QString::number(m_stdAllocatorSize); + const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName); + if (sit != m_sizeCache.constEnd()) + return QString::number(sit.value()); + // Finally have the debugger evaluate + return sizeofTypeExpression(typeName); +} + void QtDumperHelper::evaluationParameters(const WatchData &data, const TypeData &td, - Debugger /* debugger */, + Debugger debugger, QByteArray *inBuffer, QStringList *extraArgsIn) const { @@ -970,7 +1051,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, // gives already most information the dumpers need const int count = qMin(int(maxExtraArgCount), inners.size()); for (int i = 0; i < count; i++) - extraArgs.push_back(sizeofTypeExpression(inners.at(i))); + extraArgs.push_back(evaluationSizeofTypeExpression(inners.at(i), debugger)); } int extraArgCount = extraArgs.size(); // Pad with zeros @@ -1019,14 +1100,14 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, } //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype // << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0); - extraArgs[2] = sizeofTypeExpression(nodetype); + extraArgs[2] = evaluationSizeofTypeExpression(nodetype, debugger); extraArgs[3] = QLatin1String("(size_t)&(('"); extraArgs[3] += nodetype; extraArgs[3] += QLatin1String("'*)0)->value"); } break; case QMapNodeType: - extraArgs[2] = sizeofTypeExpression(data.type); + extraArgs[2] = evaluationSizeofTypeExpression(data.type, debugger); extraArgs[3] = QLatin1String("(size_t)&(('"); extraArgs[3] += data.type; extraArgs[3] += QLatin1String("'*)0)->value"); @@ -1036,7 +1117,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, if (inners.at(0) == QLatin1String("bool")) { outertype = QLatin1String("std::vector::bool"); } else { - //extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); + //extraArgs[extraArgCount++] = evaluationSizeofTypeExpression(data.type, debugger); //extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; } break; @@ -1101,11 +1182,13 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, /* Parse value: * "iname="local.sl",addr="0x0012BA84",value="<3 items>",valuedisabled="true", - * numchild="3",childtype="QString",childnumchild="0",children=[{name="0",value="<binhex>", - * valueencoded="2"},{name="1",value="dAB3AG8A",valueencoded="2"},{name="2", - * value="dABoAHIAZQBlAA==",valueencoded="2"}]" */ + * numchild="3",childtype="QString",childnumchild="0", + * children=[{name="0",value="<binhex>",valueencoded="2"}, + * {name="1",value="dAB3AG8A",valueencoded="2"}, + * {name="2",value="dABoAHIAZQBlAA==",valueencoded="2"}]" */ -class ValueDumperParser : public DumperParser { +class ValueDumperParser : public DumperParser +{ public: explicit ValueDumperParser(const char *s); @@ -1260,5 +1343,14 @@ bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r) return true; } +QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d) +{ + QDebug nsp = in.nospace(); + nsp << " type=" << d.type << " tpl=" << d.isTemplate; + if (d.isTemplate) + nsp << d.tmplate << '<' << d.inner << '>'; + return in; +} + } } diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h index 2fd9a802465d7f26349f450cce223e66200da23f..47f73a8bb79cf8e1fbf418887c961d1d782bb0bf 100644 --- a/src/plugins/debugger/watchutils.h +++ b/src/plugins/debugger/watchutils.h @@ -114,7 +114,8 @@ QDebug operator<<(QDebug in, const QtDumperResult &d); * 2) Evaluate symbol, taking address and some additional parameters * depending on type. */ -class QtDumperHelper { +class QtDumperHelper +{ public: enum Debugger { GdbDebugger, // Can evalulate expressions in function calls @@ -127,7 +128,7 @@ public: // Below types require special handling QObjectType, QWidgetType, QObjectSlotType, QObjectSignalType, QVectorType, QMapType, QMultiMapType, QMapNodeType, - StdVectorType, StdDequeType, StdSetType,StdMapType, StdStackType, + StdVectorType, StdDequeType, StdSetType, StdMapType, StdStackType, StdStringType }; @@ -181,17 +182,29 @@ public: QString toString(bool debug = false) const; -private: + void addSize(const QString &name, int size); + +private: typedef QMap<QString, Type> NameTypeMap; + typedef QMap<QString, int> SizeCache; // Look up a simple (namespace) type static Type specialType(QString s); + QString evaluationSizeofTypeExpression(const QString &typeName, Debugger d) const; + + const QString m_stdAllocatorPrefix; NameTypeMap m_nameTypeMap; + SizeCache m_sizeCache; + int m_intSize; + int m_pointerSize; + int m_stdAllocatorSize; int m_qtVersion; QString m_qtNamespace; }; +QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d); + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index d44c789d6f5ed29c74e9b4a87748943b5607b18e..f1ac66d43bf9f4e02655275c31ab85dc6f2453ca 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1499,7 +1499,7 @@ QRect BaseTextEditor::collapseBox() QTextBlock begin = document()->findBlockByNumber(d->m_highlightBlocksInfo.open.last()); - if (!d->m_displaySettings.m_fancyFoldingBar) { + if (true || !d->m_displaySettings.m_fancyFoldingBar) { if (TextBlockUserData::hasCollapseAfter(begin.previous())) begin = begin.previous(); } @@ -2231,23 +2231,6 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e) int top = (int)blockBoundingGeometry(block).translated(contentOffset()).top(); int bottom = top; -#if 0 - int extraAreaHighlightCollapseEndBlockNumber = -1; - - int extraAreaHighlightCollapseBlockNumber = d->extraAreaHighlightCollapseBlockNumber; - if (extraAreaHighlightCollapseBlockNumber < 0) { - extraAreaHighlightCollapseBlockNumber = d->extraAreaHighlightFadingBlockNumber; - } - - if (extraAreaHighlightCollapseBlockNumber >= 0 ) { - QTextBlock highlightBlock = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber); - if (highlightBlock.isValid() && highlightBlock.next().isValid() && highlightBlock.next().isVisible()) - extraAreaHighlightCollapseEndBlockNumber = TextBlockUserData::testCollapse(highlightBlock).blockNumber(); - else - extraAreaHighlightCollapseEndBlockNumber = extraAreaHighlightCollapseBlockNumber; - } -#endif - while (block.isValid() && top <= e->rect().bottom()) { top = bottom; @@ -2304,20 +2287,29 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e) QRect r(extraAreaWidth+2, top, collapseBoxWidth-4, bottom - top); bool drawBox = !nextBlock.isVisible(); - int minBraceDepth = qMax(braceDepth, previousBraceDepth); - if (minBraceDepth > 0) { - QColor color = calcBlendColor(baseColor, minBraceDepth); - if (!d->m_highlightBlocksInfo.isEmpty() - && blockNumber >= d->m_highlightBlocksInfo.open.last() - && blockNumber <= d->m_highlightBlocksInfo.close.first()) - color = calcMixColor(pal.highlight().color(), color); - painter.fillRect(r, color); + int extraAreaHighlightCollapseBlockNumber = -1; + int extraAreaHighlightCollapseEndBlockNumber = -1; + if (!d->m_highlightBlocksInfo.isEmpty()) { + extraAreaHighlightCollapseBlockNumber = d->m_highlightBlocksInfo.open.last(); + extraAreaHighlightCollapseEndBlockNumber = d->m_highlightBlocksInfo.close.first(); + + QTextBlock before = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber-1); + if (TextBlockUserData::hasCollapseAfter(before)) { + extraAreaHighlightCollapseBlockNumber--; + } } + int minBraceDepth = qMax(braceDepth, previousBraceDepth); + QColor color = calcBlendColor(baseColor, minBraceDepth); + if (!d->m_highlightBlocksInfo.isEmpty() + && blockNumber >= extraAreaHighlightCollapseBlockNumber + && blockNumber <= extraAreaHighlightCollapseEndBlockNumber) + color = calcMixColor(pal.highlight().color(), color); + painter.fillRect(r, color); bool drawDown = !d->m_highlightBlocksInfo.isEmpty() - && blockNumber == d->m_highlightBlocksInfo.open.last(); + && blockNumber == extraAreaHighlightCollapseBlockNumber; bool drawUp = !d->m_highlightBlocksInfo.isEmpty() - && blockNumber == d->m_highlightBlocksInfo.close.first(); + && blockNumber == extraAreaHighlightCollapseEndBlockNumber; if (drawBox || drawDown || drawUp) { painter.setRenderHint(QPainter::Antialiasing, true); @@ -2337,7 +2329,7 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e) } else if (drawUp) { // check that we are not collapsed - QTextBlock open = doc->findBlockByNumber(d->m_highlightBlocksInfo.open.last()); + QTextBlock open = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber); if (open.next().isVisible()) { QPointF points[3] = { QPointF(r.left(), r.bottom()-1), @@ -2347,8 +2339,8 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e) } } else if(drawDown) { QPointF points[3] = { QPointF(r.left(), r.top()), - QPointF(r.center().x(), r.center().y()), - QPointF(r.right(), r.top()) }; + QPointF(r.center().x(), r.center().y()), + QPointF(r.right(), r.top()) }; painter.drawPolygon(points, 3); } painter.translate(-.5, -.5); @@ -2378,8 +2370,8 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e) extraAreaHighlightCollapseEndBlockNumber = d->m_highlightBlocksInfo.close.first(); endIsVisible = doc->findBlockByNumber(extraAreaHighlightCollapseEndBlockNumber).isVisible(); - if (TextBlockUserData::hasCollapseAfter( - doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber-1))) { + QTextBlock before = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber-1); + if (TextBlockUserData::hasCollapseAfter(before)) { extraAreaHighlightCollapseBlockNumber--; } } @@ -2698,12 +2690,15 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e) int collapseBoxWidth = fontMetrics().lineSpacing() + 1; if (e->pos().x() > extraArea()->width() - collapseBoxWidth) { d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber(); - if (!TextBlockUserData::hasClosingCollapse(cursor.block())) + if (TextBlockUserData::canCollapse(cursor.block()) + || !TextBlockUserData::hasClosingCollapse(cursor.block())) d->extraAreaHighlightCollapseColumn = cursor.block().length()-1; - if (!d->m_displaySettings.m_fancyFoldingBar + if ((true || !d->m_displaySettings.m_fancyFoldingBar) && TextBlockUserData::hasCollapseAfter(cursor.block())) { d->extraAreaHighlightCollapseBlockNumber++; - if (!TextBlockUserData::hasClosingCollapse(cursor.block().next())) + d->extraAreaHighlightCollapseColumn = -1; + if (TextBlockUserData::canCollapse(cursor.block().next()) + || !TextBlockUserData::hasClosingCollapse(cursor.block().next())) d->extraAreaHighlightCollapseColumn = cursor.block().next().length()-1; } } @@ -3299,8 +3294,9 @@ bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor, bo if (block == cursor->block()) { if (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0)) continue; - if (checkStartPosition && paren.type == Parenthesis::Opened && position == cursor->position()) + if (checkStartPosition && paren.type == Parenthesis::Opened && paren.pos== cursor->position()) { return true; + } } if (paren.type == Parenthesis::Closed) { ++ignore; @@ -3820,6 +3816,10 @@ void BaseTextEditor::setDisplaySettings(const DisplaySettings &ds) } d->m_displaySettings = ds; + d->extraAreaHighlightCollapseBlockNumber = d->extraAreaHighlightCollapseColumn = -1; + d->m_highlightBlocksInfo = BaseTextEditorPrivateHighlightBlocks(); + viewport()->update(); + extraArea()->update(); } void BaseTextEditor::setStorageSettings(const StorageSettings &storageSettings) diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index ca488ba1c8de9ae5ee11087a0bab2f807d9fb05e..15cc8d962886b0d87d9a8bf0fd555bd0235df1a5 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -143,10 +143,12 @@ public: inline static bool hasCollapseAfter(const QTextBlock & block) { + if (!block.isValid()) + return false; TextBlockUserData *data = static_cast<TextBlockUserData*>(block.userData()); if (data && data->collapseMode() != NoCollapse) { - return (data->collapseMode() == CollapseAfter); - } else if (!data) { + return false; + } else if (block.next().isValid()) { data = static_cast<TextBlockUserData*>(block.next().userData()); if (data && data->collapseMode() == TextBlockUserData::CollapseThis && !data->m_ifdefedOut) return true; diff --git a/src/plugins/texteditor/basetextmark.cpp b/src/plugins/texteditor/basetextmark.cpp index c4bbbb32277d83cc20b8e8743636b20b715dd417..94c03d5455a80473a68c73e184c4df10ee47bdd3 100644 --- a/src/plugins/texteditor/basetextmark.cpp +++ b/src/plugins/texteditor/basetextmark.cpp @@ -61,8 +61,13 @@ void BaseTextMark::init() void BaseTextMark::editorOpened(Core::IEditor *editor) { +#ifdef Q_OS_WIN + if (m_fileName.compare(editor->file()->fileName(), Qt::CaseInsensitive)) + return; +#else if (editor->file()->fileName() != m_fileName) return; +#endif if (ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor)) { if (m_markableInterface == 0) { // We aren't added to something m_markableInterface = textEditor->markableInterface(); diff --git a/tests/auto/qstringbuilder/qstringbuilder.pro b/tests/auto/qstringbuilder/qstringbuilder.pro new file mode 100644 index 0000000000000000000000000000000000000000..5416ca413ab313bea694286ce9a4c72d84466e2d --- /dev/null +++ b/tests/auto/qstringbuilder/qstringbuilder.pro @@ -0,0 +1,11 @@ +load(qttest_p4) +SOURCES += tst_qstringbuilder.cpp + +QT -= gui + +QT = core + +DEFINES += QT_NO_CAST_TO_ASCII + + + diff --git a/tests/auto/qstringbuilder/tst_qstringbuilder.cpp b/tests/auto/qstringbuilder/tst_qstringbuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e58d1252aa3386a58335948a6457c99401a6982 --- /dev/null +++ b/tests/auto/qstringbuilder/tst_qstringbuilder.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include "../../../src/libs/utils/qstringbuilder.h" + +//TESTED_CLASS=QStringBuilder +//TESTED_FILES=qstringbuilder.h + +class tst_QStringBuilder : public QObject +{ + Q_OBJECT + +public: + tst_QStringBuilder(); + ~tst_QStringBuilder() {} + +public slots: + void init() {} + void cleanup() {} + +private slots: + void operator_percent(); +}; + + +tst_QStringBuilder::tst_QStringBuilder() +{ + //QTextCodec::setCodecForLocale(QTextCodec::codecForName("ISO 8859-1")); +} + +void tst_QStringBuilder::operator_percent() +{ + QLatin1Literal l1literal("a literal"); + QLatin1String l1string("a literal"); + QLatin1Char l1char('c'); + QChar qchar(l1char); + + QCOMPARE(QString(l1literal % l1literal), QString(l1string + l1string)); +} + +QTEST_APPLESS_MAIN(tst_QStringBuilder) + +#include "tst_qstringbuilder.moc" diff --git a/tests/benchmarks/qstringbuilder/main.cpp b/tests/benchmarks/qstringbuilder/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba5cfe0a762e42aa674a9eaa3fe3decbffa980c8 --- /dev/null +++ b/tests/benchmarks/qstringbuilder/main.cpp @@ -0,0 +1,106 @@ + +#include <QDebug> +#include <QString> + +#include "../../../src/libs/utils/qstringbuilder.h" + +#include <qtest.h> + + +class tst_qstringbuilder : public QObject +{ + Q_OBJECT + +public: + tst_qstringbuilder(); + +private slots: + // QStringBuilder based + void b_separator() { qDebug() << "\n------- QStringBuilder based ----------"; } + void b_2_l1literal(); + void b_3_l1literal(); + void b_4_l1literal(); + void b_string_4_char(); + + // QString based for comparison + void s_separator() { qDebug() << "\n-------- QString based ---------"; } + void s_2_l1string(); + void s_3_l1string(); + void s_4_l1string(); + void s_string_4_char(); + +private: + const QLatin1Literal l1literal; + const QLatin1String l1string; + const QString string; + const char achar; +}; + + +tst_qstringbuilder::tst_qstringbuilder() + : l1literal("some literal"), + l1string("some literal"), + string(l1string), + achar('c') +{} + +void tst_qstringbuilder::b_2_l1literal() +{ + QString result; + QBENCHMARK { result = l1literal % l1literal; } + QCOMPARE(result, l1string + l1string); +} + +void tst_qstringbuilder::b_3_l1literal() +{ + QString result; + QBENCHMARK { result = l1literal % l1literal % l1literal; } + QCOMPARE(result, l1string + l1string + l1string); +} + +void tst_qstringbuilder::b_4_l1literal() +{ + QString result; + QBENCHMARK { result = l1literal % l1literal % l1literal % l1literal; } + QCOMPARE(result, l1string + l1string + l1string + l1string); +} + +void tst_qstringbuilder::b_string_4_char() +{ + QString result; + QBENCHMARK { result = string + achar + achar + achar; } + QCOMPARE(result, QString(string % achar % achar % achar)); +} + + +void tst_qstringbuilder::s_2_l1string() +{ + QString result; + QBENCHMARK { result = l1string + l1string; } + QCOMPARE(result, QString(l1literal % l1literal)); +} + +void tst_qstringbuilder::s_3_l1string() +{ + QString result; + QBENCHMARK { result = l1string + l1string + l1string; } + QCOMPARE(result, QString(l1literal % l1literal % l1literal)); +} + +void tst_qstringbuilder::s_4_l1string() +{ + QString result; + QBENCHMARK { result = l1string + l1string + l1string + l1string; } + QCOMPARE(result, QString(l1literal % l1literal % l1literal % l1literal)); +} + +void tst_qstringbuilder::s_string_4_char() +{ + QString result; + QBENCHMARK { result = string + achar + achar + achar; } + QCOMPARE(result, QString(string % achar % achar % achar)); +} + +QTEST_MAIN(tst_qstringbuilder) + +#include "main.moc" diff --git a/tests/benchmarks/qstringbuilder/qstringbuilder.pro b/tests/benchmarks/qstringbuilder/qstringbuilder.pro new file mode 100644 index 0000000000000000000000000000000000000000..81c42bc565d2fa4183dad8022d125f26fc4f4f31 --- /dev/null +++ b/tests/benchmarks/qstringbuilder/qstringbuilder.pro @@ -0,0 +1,12 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qstringbuilder +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui + +CONFIG += release + +# Input +SOURCES += main.cpp diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 608198bb28de4f70d4631c920790b70ff9fa909c..a5b0d0c2a6ab2a0d5343fa4e5b7f3eb41d63d439 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -549,9 +549,13 @@ void testQSharedPointer() QSharedPointer<QString> ptr2 = ptr; QSharedPointer<QString> ptr3 = ptr; - //QWeakPointer<QString> wptr(ptr); - //QWeakPointer<QString> wptr2 = wptr; - //QWeakPointer<QString> wptr3 = wptr; + QWeakPointer<int> wiptr(iptr); + QWeakPointer<int> wiptr2 = wiptr; + QWeakPointer<int> wiptr3 = wiptr; + + QWeakPointer<QString> wptr(ptr); + QWeakPointer<QString> wptr2 = wptr; + QWeakPointer<QString> wptr3 = wptr; } void stringRefTest(const QString &refstring)