diff options
Diffstat (limited to 'src/corelib')
27 files changed, 646 insertions, 122 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index ac2f72d573..3006c75794 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2813,12 +2813,15 @@ QString QSysInfo::prettyProductName() \macro void Q_CHECK_PTR(void *pointer) \relates <QtGlobal> - If \a pointer is 0, prints a warning message containing the source + If \a pointer is 0, prints a message containing the source code's file name and line number, saying that the program ran out - of memory. + of memory and aborts program execution. It throws \c std::bad_alloc instead + if exceptions are enabled. - Q_CHECK_PTR does nothing if \c QT_NO_DEBUG was defined during - compilation. + Q_CHECK_PTR does nothing if \c QT_NO_DEBUG and \c QT_NO_EXCEPTIONS were + defined during compilation. Therefore you must not use Q_CHECK_PTR to check + for successful memory allocations because the check will be disabled in + some cases. Example: diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 27a3bf7c3d..c4e2f7609c 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -41,11 +41,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.5.0" +#define QT_VERSION_STR "5.6.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050500 +#define QT_VERSION 0x050600 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 436bf8dd57..b87dbe4784 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -83,10 +83,11 @@ public: Qt_5_3 = Qt_5_2, Qt_5_4 = 16, Qt_5_5 = Qt_5_4, -#if QT_VERSION >= 0x050600 + Qt_5_6 = Qt_5_5, +#if QT_VERSION >= 0x050700 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_5 + Qt_DefaultCompiledVersion = Qt_5_6 }; enum ByteOrder { diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 357d63137c..8676fe0259 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -334,6 +334,7 @@ QDebug &QDebug::resetFormat() stream->space = true; if (stream->context.version > 1) stream->flags = 0; + stream->setVerbosity(Stream::defaultVerbosity); return *this; } @@ -424,6 +425,32 @@ QDebug &QDebug::resetFormat() */ /*! + \fn int QDebug::verbosity() const + \since 5.6 + + Returns the verbosity of the debug stream. + + Streaming operators can check the value to decide whether + verbose output is desired and print more information depending on the + level. Higher values indicate that more information is desired. + + The allowed range is from 0 to 7. The default value is 2. + + \sa setVerbosity() +*/ + +/*! + \fn void QDebug::setVerbosity(int verbosityLevel) + \since 5.6 + + Sets the verbosity of the stream to \a verbosityLevel. + + The allowed range is from 0 to 7. The default value is 2. + + \sa verbosity() +*/ + +/*! \fn QDebug &QDebug::operator<<(QChar t) Writes the character, \a t, to the stream and returns a reference to the diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 59bd32e9a4..9391799624 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -53,9 +53,14 @@ class Q_CORE_EXPORT QDebug friend class QMessageLogger; friend class QDebugStateSaverPrivate; struct Stream { - Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false), flags(0) {} - Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false), flags(0) {} - Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), space(true), message_output(true), flags(0) {} + enum { defaultVerbosity = 2, verbosityShift = 29, verbosityMask = 0x7 }; + + Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), + space(true), message_output(false), flags(defaultVerbosity << verbosityShift) {} + Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), + space(true), message_output(false), flags(defaultVerbosity << verbosityShift) {} + Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t), + space(true), message_output(true), flags(defaultVerbosity << verbosityShift) {} QTextStream ts; QString buffer; int ref; @@ -64,7 +69,7 @@ class Q_CORE_EXPORT QDebug bool message_output; QMessageLogContext context; - enum FormatFlag { + enum FormatFlag { // Note: Bits 29..31 are reserved for the verbose level introduced in 5.6. NoQuotes = 0x1 }; @@ -72,7 +77,15 @@ class Q_CORE_EXPORT QDebug bool testFlag(FormatFlag flag) const { return (context.version > 1) ? (flags & flag) : false; } void setFlag(FormatFlag flag) { if (context.version > 1) { flags |= flag; } } void unsetFlag(FormatFlag flag) { if (context.version > 1) { flags &= ~flag; } } - + int verbosity() const + { return context.version > 1 ? (flags >> verbosityShift) & verbosityMask : int(Stream::defaultVerbosity); } + void setVerbosity(int v) + { + if (context.version > 1) { + flags &= ~(verbosityMask << verbosityShift); + flags |= (v & verbosityMask) << verbosityShift; + } + } // added in 5.4 int flags; } *stream; @@ -96,6 +109,8 @@ public: inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; } inline QDebug &nospace() { stream->space = false; return *this; } inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; } + int verbosity() const { return stream->verbosity(); } + void setVerbosity(int verbosityLevel) { stream->setVerbosity(verbosityLevel); } bool autoInsertSpaces() const { return stream->space; } void setAutoInsertSpaces(bool b) { stream->space = b; } diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index 3ee0e33573..4c5ed0aef6 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -481,7 +481,7 @@ bool QFileDevicePrivate::putCharHelper(char c) #else // Cutoff for code that doesn't only touch the buffer. - int writeBufferSize = writeBuffer.size(); + qint64 writeBufferSize = writeBuffer.size(); if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE #ifdef Q_OS_WIN || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 6451bae0ba..d5c861f9ad 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1912,12 +1912,12 @@ qint64 QProcess::readData(char *data, qint64 maxlen) return 1; } - qint64 bytesToRead = qint64(qMin(readBuffer->size(), (int)maxlen)); + qint64 bytesToRead = qMin(readBuffer->size(), maxlen); qint64 readSoFar = 0; while (readSoFar < bytesToRead) { const char *ptr = readBuffer->readPointer(); - int bytesToReadFromThisBlock = qMin<qint64>(bytesToRead - readSoFar, - readBuffer->nextDataBlockSize()); + qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, + readBuffer->nextDataBlockSize()); memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock); readSoFar += bytesToReadFromThisBlock; readBuffer->free(bytesToReadFromThisBlock); diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index ab2025ee5c..1502e5dada 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -45,8 +45,8 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent) handle(INVALID_HANDLE_VALUE), readBufferMaxSize(0), actualReadBufferSize(0), - readSequenceStarted(false), emitReadyReadTimer(new QTimer(this)), + readSequenceStarted(false), pipeBroken(false), readyReadEmitted(false) { @@ -133,12 +133,12 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) actualReadBufferSize--; readSoFar = 1; } else { - qint64 bytesToRead = qMin(qint64(actualReadBufferSize), maxlen); + qint64 bytesToRead = qMin(actualReadBufferSize, maxlen); readSoFar = 0; while (readSoFar < bytesToRead) { const char *ptr = readBuffer.readPointer(); - int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, - qint64(readBuffer.nextDataBlockSize())); + qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, + readBuffer.nextDataBlockSize()); memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock); readSoFar += bytesToReadFromThisBlock; readBuffer.free(bytesToReadFromThisBlock); diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h index 7904f116cb..53872e2552 100644 --- a/src/corelib/io/qwindowspipereader_p.h +++ b/src/corelib/io/qwindowspipereader_p.h @@ -98,9 +98,9 @@ private: QWinOverlappedIoNotifier *dataReadNotifier; qint64 readBufferMaxSize; QRingBuffer readBuffer; - int actualReadBufferSize; - bool readSequenceStarted; + qint64 actualReadBufferSize; QTimer *emitReadyReadTimer; + bool readSequenceStarted; bool pipeBroken; bool readyReadEmitted; }; diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index b2b22ad99c..0a68de8871 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -150,7 +150,7 @@ QT_BEGIN_NAMESPACE \value HoverLeave The mouse cursor leaves a hover widget (QHoverEvent). \value HoverMove The mouse cursor moves inside a hover widget (QHoverEvent). \value IconDrag The main icon of a window has been dragged away (QIconDragEvent). - \value IconTextChange Widget's icon text has been changed. + \value IconTextChange Widget's icon text has been changed. (Deprecated) \value InputMethod An input method is being used (QInputMethodEvent). \value InputMethodQuery A input method query event (QInputMethodQueryEvent) \value KeyboardLayoutChange The keyboard layout has changed. diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index c208eb1180..53da4a849b 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -133,7 +133,7 @@ public: EnabledChange = 98, // enabled state has changed ActivationChange = 99, // window activation has changed StyleChange = 100, // style has changed - IconTextChange = 101, // icon text has changed + IconTextChange = 101, // icon text has changed. Deprecated. ModifiedChange = 102, // modified state has changed MouseTrackingChange = 109, // mouse tracking state has changed diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 22c0f03afc..097f641d19 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -204,6 +204,15 @@ static jfieldID getCachedFieldID(JNIEnv *env, } } +void QJNILocalRefDeleter::cleanup(jobject obj) +{ + if (obj == 0) + return; + + QJNIEnvironmentPrivate env; + env->DeleteLocalRef(obj); +} + class QJNIEnvironmentPrivateTLS { public: @@ -2259,4 +2268,3 @@ bool QJNIObjectPrivate::isSameObject(const QJNIObjectPrivate &other) const } QT_END_NAMESPACE - diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index e79caed5b8..ae9c7c3a7e 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -51,6 +51,14 @@ QT_BEGIN_NAMESPACE +struct Q_CORE_EXPORT QJNILocalRefDeleter +{ + static void cleanup(jobject obj); +}; + +// To simplify this we only define it for jobjects. +typedef QScopedPointer<_jobject, QJNILocalRefDeleter> QJNIScopedLocalRef; + class Q_CORE_EXPORT QJNIEnvironmentPrivate { public: diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index dad2d5dc1e..f77fc4220c 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -122,6 +122,45 @@ void QtAndroidPrivate::handleNewIntent(JNIEnv *env, jobject intent) } } +namespace { + class ResumePauseListeners + { + public: + QMutex mutex; + QList<QtAndroidPrivate::ResumePauseListener *> listeners; + }; +} + +Q_GLOBAL_STATIC(ResumePauseListeners, g_resumePauseListeners) + +void QtAndroidPrivate::registerResumePauseListener(ResumePauseListener *listener) +{ + QMutexLocker locker(&g_resumePauseListeners()->mutex); + g_resumePauseListeners()->listeners.append(listener); +} + +void QtAndroidPrivate::unregisterResumePauseListener(ResumePauseListener *listener) +{ + QMutexLocker locker(&g_resumePauseListeners()->mutex); + g_resumePauseListeners()->listeners.removeAll(listener); +} + +void QtAndroidPrivate::handlePause() +{ + QMutexLocker locker(&g_resumePauseListeners()->mutex); + const QList<QtAndroidPrivate::ResumePauseListener *> &listeners = g_resumePauseListeners()->listeners; + for (int i=0; i<listeners.size(); ++i) + listeners.at(i)->handlePause(); +} + +void QtAndroidPrivate::handleResume() +{ + QMutexLocker locker(&g_resumePauseListeners()->mutex); + const QList<QtAndroidPrivate::ResumePauseListener *> &listeners = g_resumePauseListeners()->listeners; + for (int i=0; i<listeners.size(); ++i) + listeners.at(i)->handleResume(); +} + static inline bool exceptionCheck(JNIEnv *env) { if (env->ExceptionCheck()) { diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 3ed8338b18..883b08ef60 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -68,6 +68,14 @@ namespace QtAndroidPrivate virtual bool handleNewIntent(JNIEnv *env, jobject intent) = 0; }; + class Q_CORE_EXPORT ResumePauseListener + { + public: + virtual ~ResumePauseListener() {} + virtual void handlePause() {}; + virtual void handleResume() {}; + }; + Q_CORE_EXPORT jobject activity(); Q_CORE_EXPORT JavaVM *javaVM(); Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env); @@ -82,6 +90,11 @@ namespace QtAndroidPrivate Q_CORE_EXPORT void handleNewIntent(JNIEnv *env, jobject intent); Q_CORE_EXPORT void registerNewIntentListener(NewIntentListener *listener); Q_CORE_EXPORT void unregisterNewIntentListener(NewIntentListener *listener); + + Q_CORE_EXPORT void handlePause(); + Q_CORE_EXPORT void handleResume(); + Q_CORE_EXPORT void registerResumePauseListener(ResumePauseListener *listener); + Q_CORE_EXPORT void unregisterResumePauseListener(ResumePauseListener *listener); } QT_END_NAMESPACE diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 8ed9199c60..2800656c13 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -273,6 +273,13 @@ bool QPluginLoader::isLoaded() const #if defined(QT_SHARED) static QString locatePlugin(const QString& fileName) { + const bool isAbsolute = QDir::isAbsolutePath(fileName); + if (isAbsolute) { + QFileInfo fi(fileName); + if (fi.isFile()) { + return fi.canonicalFilePath(); + } + } QStringList prefixes = QLibraryPrivate::prefixes_sys(); prefixes.prepend(QString()); QStringList suffixes = QLibraryPrivate::suffixes_sys(QString()); @@ -281,12 +288,18 @@ static QString locatePlugin(const QString& fileName) // Split up "subdir/filename" const int slash = fileName.lastIndexOf('/'); const QString baseName = fileName.mid(slash + 1); - const QString basePath = fileName.left(slash + 1); // keep the '/' + const QString basePath = isAbsolute ? QString() : fileName.left(slash + 1); // keep the '/' const bool debug = qt_debug_component(); - QStringList paths = QCoreApplication::libraryPaths(); - paths.prepend(QStringLiteral("./")); // search in current dir first + QStringList paths; + if (isAbsolute) { + paths.append(fileName.left(slash)); // don't include the '/' + } else { + paths = QCoreApplication::libraryPaths(); + paths.prepend(QStringLiteral(".")); // search in current dir first + } + foreach (const QString &path, paths) { foreach (const QString &prefix, prefixes) { foreach (const QString &suffix, suffixes) { @@ -337,12 +350,7 @@ void QPluginLoader::setFileName(const QString &fileName) did_load = false; } - QFileInfo fi(fileName); - QString fn; - if (fi.isAbsolute()) - fn = fi.canonicalFilePath(); - else - fn = locatePlugin(fileName); + const QString fn = locatePlugin(fileName); d = QLibraryPrivate::findOrCreate(fn, QString(), lh); if (!fn.isEmpty()) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 760ac59bf4..a681688d46 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1430,9 +1430,11 @@ void QStateMachinePrivate::_q_process() Q_ASSERT(!processing); processing = true; processingScheduled = false; + beginMacrostep(); #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": starting the event processing loop"; #endif + bool didChange = false; while (processing) { if (stop) { processing = false; @@ -1473,15 +1475,17 @@ void QStateMachinePrivate::_q_process() } } if (!enabledTransitions.isEmpty()) { + didChange = true; q->beginMicrostep(e); microstep(e, enabledTransitions.toList()); q->endMicrostep(e); } -#ifdef QSTATEMACHINE_DEBUG else { + noMicrostep(); +#ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": no transitions enabled"; - } #endif + } delete e; } #ifdef QSTATEMACHINE_DEBUG @@ -1494,6 +1498,7 @@ void QStateMachinePrivate::_q_process() switch (stopProcessingReason) { case EventQueueEmpty: + processedPendingEvents(didChange); break; case Finished: state = NotRunning; @@ -1510,6 +1515,7 @@ void QStateMachinePrivate::_q_process() emit q->runningChanged(false); break; } + endMacrostep(didChange); } void QStateMachinePrivate::_q_startDelayedEventTimer(int id, int delay) @@ -1619,6 +1625,47 @@ void QStateMachinePrivate::cancelAllDelayedEvents() delayedEvents.clear(); } +/* + This function is called when the state machine is performing no + microstep because no transition is enabled (i.e. an event is ignored). + + The default implementation does nothing. +*/ +void QStateMachinePrivate::noMicrostep() +{ } + +/* + This function is called when the state machine has reached a stable + state (no pending events), and has not finished yet. + For each event the state machine receives it is guaranteed that + 1) beginMacrostep is called + 2) selectTransition is called at least once + 3) begin/endMicrostep is called at least once or noMicrostep is called + at least once (possibly both, but at least one) + 4) the state machine either enters an infinite loop, or stops (runningChanged(false), + and either finished or stopped are emitted), or processedPendingEvents() is called. + 5) if the machine is not in an infinite loop endMacrostep is called + + didChange is set to true if at least one microstep was performed, it is possible + that the machine returned to exactly the same state as before, but some transitions + were triggered. + + The default implementation does nothing. +*/ +void QStateMachinePrivate::processedPendingEvents(bool didChange) +{ + Q_UNUSED(didChange); +} + +void QStateMachinePrivate::beginMacrostep() +{ } + +void QStateMachinePrivate::endMacrostep(bool didChange) +{ + Q_UNUSED(didChange); +} + + namespace _QStateMachine_Internal{ class GoToStateTransition : public QAbstractTransition diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 3a93c47c5b..b7f2644255 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -123,6 +123,10 @@ public: QAbstractTransition *createInitialTransition() const; void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList); + virtual void noMicrostep(); + virtual void processedPendingEvents(bool didChange); + virtual void beginMacrostep(); + virtual void endMacrostep(bool didChange); bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const; QSet<QAbstractTransition*> selectTransitions(QEvent *event) const; void exitStates(QEvent *event, const QList<QAbstractState *> &statesToExit_sorted, diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index ff4d5a3ebd..57fbdf0eba 100644..100755 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -584,6 +584,131 @@ Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qPopulationCount(long unsigne #undef QALGORITHMS_USE_BUILTIN_POPCOUNT #endif +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctz(v) : 32U; +#else + // see http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightParallel + unsigned int c = 32; // c will be the number of zero bits on the right + v &= -signed(v); + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctz(v) : 8U; +#else + unsigned int c = 8; // c will be the number of zero bits on the right + v &= -signed(v); + if (v) c--; + if (v & 0x0000000F) c -= 4; + if (v & 0x00000033) c -= 2; + if (v & 0x00000055) c -= 1; + return c; +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctz(v) : 16U; +#else + unsigned int c = 16; // c will be the number of zero bits on the right + v &= -signed(v); + if (v) c--; + if (v & 0x000000FF) c -= 8; + if (v & 0x00000F0F) c -= 4; + if (v & 0x00003333) c -= 2; + if (v & 0x00005555) c -= 1; + return c; +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint64 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctzll(v) : 64; +#else + quint32 x = static_cast<quint32>(v); + return x ? qCountTrailingZeroBits(x) + : 32 + qCountTrailingZeroBits(static_cast<quint32>(v >> 32)); +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) Q_DECL_NOTHROW +{ + return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clz(v) : 32U; +#else + // Hacker's Delight, 2nd ed. Fig 5-16, p. 102 + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + v = v | (v >> 8); + v = v | (v >> 16); + return qPopulationCount(~v); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clz(v)-24U : 8U; +#else + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + return qPopulationCount(static_cast<quint8>(~v)); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clz(v)-16U : 16U; +#else + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + v = v | (v >> 8); + return qPopulationCount(static_cast<quint16>(~v)); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clzll(v) : 64U; +#else + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + v = v | (v >> 8); + v = v | (v >> 16); + v = v | (v >> 32); + return qPopulationCount(~v); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW +{ + return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); +} + QT_WARNING_POP QT_END_NAMESPACE diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index 193042e017..dac353fa70 100644..100755 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -785,3 +785,73 @@ \since 5.2 \overload */ + +/*! + \fn uint qCountTrailingZeroBits(quint8 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the LSB. + For example, qCountTrailingZeroBits(1) returns 0 and qCountTrailingZeroBits(8) returns 3. + */ + +/*! + \fn uint qCountTrailingZeroBits(quint16 v) + \relates <QtAlgorithms> + \since 5.6 + \overload + */ + +/*! + \fn uint qCountTrailingZeroBits(quint32 v) + \relates <QtAlgorithms> + \since 5.6 + \overload + */ + +/*! + \fn uint qCountTrailingZeroBits(quint64 v) + \relates <QtAlgorithms> + \since 5.6 + \overload + */ + +/*! + \fn uint qCountLeadingZeroBits(quint8 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint8(1)) returns 7 and + qCountLeadingZeroBits(quint8(8)) returns 4. + */ + +/*! + \fn uint qCountLeadingZeroBits(quint16 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint16(1)) returns 15 and + qCountLeadingZeroBits(quint16(8)) returns 12. + */ + +/*! + \fn uint qCountLeadingZeroBits(quint32 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint32(1)) returns 31 and + qCountLeadingZeroBits(quint32(8)) returns 28. + */ + +/*! + \fn uint qCountLeadingZeroBits(quint64 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint64(1)) returns 63 and + qCountLeadingZeroBits(quint64(8)) returns 60. + */ diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index 7f898f68a8..51723f4a57 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -42,6 +42,7 @@ class QCommandLineOptionPrivate : public QSharedData { public: inline QCommandLineOptionPrivate() + : hidden(false) { } void setNames(const QStringList &nameList); @@ -58,6 +59,9 @@ public: //! The list of default values used for this option. QStringList defaultValues; + + //! Show or hide in --help + bool hidden; }; /*! @@ -362,4 +366,30 @@ QStringList QCommandLineOption::defaultValues() const return d->defaultValues; } +/*! + Sets whether to hide this option in the user-visible help output. + + All options are visible by default. Setting \a hidden to true for + a particular option makes it internal, i.e. not listed in the help output. + + \since 5.6 + \sa isHidden + */ +void QCommandLineOption::setHidden(bool hide) +{ + d->hidden = hide; +} + +/*! + Returns true if this option is omitted from the help output, + false if the option is listed. + + \since 5.6 + \sa setHidden() + */ +bool QCommandLineOption::isHidden() const +{ + return d->hidden; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h index cf4160ecd2..85fc5ca6dd 100644 --- a/src/corelib/tools/qcommandlineoption.h +++ b/src/corelib/tools/qcommandlineoption.h @@ -77,6 +77,9 @@ public: void setDefaultValues(const QStringList &defaultValues); QStringList defaultValues() const; + void setHidden(bool hidden); + bool isHidden() const; + private: QSharedDataPointer<QCommandLineOptionPrivate> d; }; diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 21bc14a272..7e49253f9b 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -53,6 +53,7 @@ class QCommandLineParserPrivate public: inline QCommandLineParserPrivate() : singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions), + optionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsOptions), builtinVersionOption(false), builtinHelpOption(false), needsParsing(true) @@ -103,6 +104,9 @@ public: //! The parsing mode for "-abc" QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode; + //! How to parse "arg -option" + QCommandLineParser::OptionsAfterPositionalArgumentsMode optionsAfterPositionalArgumentsMode; + //! Whether addVersionOption was called bool builtinVersionOption; @@ -299,6 +303,41 @@ void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleD } /*! + \enum QCommandLineParser::OptionsAfterPositionalArgumentsMode + + This enum describes the way the parser interprets options that + occur after positional arguments. + + \value ParseAsOptions \c{application argument --opt -t} is interpreted as setting + the options \c{opt} and \c{t}, just like \c{application --opt -t argument} would do. + This is the default parsing mode. In order to specify that \c{--opt} and \c{-t} + are positional arguments instead, the user can use \c{--}, as in + \c{application argument -- --opt -t}. + + \value ParseAsPositionalArguments \c{application argument --opt} is interpreted as + having two positional arguments, \c{argument} and \c{--opt}. + This mode is useful for executables that aim to launch other executables + (e.g. wrappers, debugging tools, etc.) or that support internal commands + followed by options for the command. \c{argument} is the name of the command, + and all options occurring after it can be collected and parsed by another + command line parser, possibly in another executable. + + \sa setOptionsAfterPositionalArgumentsMode() + + \since 5.5 +*/ + +/*! + Sets the parsing mode to \a parsingMode. + This must be called before process() or parse(). + \since 5.5 +*/ +void QCommandLineParser::setOptionsAfterPositionalArgumentsMode(QCommandLineParser::OptionsAfterPositionalArgumentsMode parsingMode) +{ + d->optionsAfterPositionalArgumentsMode = parsingMode; +} + +/*! Adds the option \a option to look for while parsing. Returns \c true if adding the option was successful; otherwise returns \c false. @@ -640,7 +679,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) const QLatin1Char dashChar('-'); const QLatin1Char assignChar('='); - bool doubleDashFound = false; + bool forcePositional = false; errorText.clear(); positionalArgumentList.clear(); optionNames.clear(); @@ -658,7 +697,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) for (; argumentIterator != args.end() ; ++argumentIterator) { QString argument = *argumentIterator; - if (doubleDashFound) { + if (forcePositional) { positionalArgumentList.append(argument); } else if (argument.startsWith(doubleDashString)) { if (argument.length() > 2) { @@ -670,7 +709,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) error = true; } } else { - doubleDashFound = true; + forcePositional = true; } } else if (argument.startsWith(dashChar)) { if (argument.size() == 1) { // single dash ("stdin") @@ -722,6 +761,8 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) } } else { positionalArgumentList.append(argument); + if (optionsAfterPositionalArgumentsMode == QCommandLineParser::ParseAsPositionalArguments) + forcePositional = true; } if (argumentIterator == args.end()) break; @@ -1062,6 +1103,8 @@ QString QCommandLineParserPrivate::helpText() const ++longestOptionNameString; for (int i = 0; i < commandLineOptionList.count(); ++i) { const QCommandLineOption &option = commandLineOptionList.at(i); + if (option.isHidden()) + continue; text += wrapText(optionNameList.at(i), longestOptionNameString, option.description()); } if (!positionalArgumentDefinitions.isEmpty()) { diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h index 91a799b4d5..8c528ba69e 100644 --- a/src/corelib/tools/qcommandlineparser.h +++ b/src/corelib/tools/qcommandlineparser.h @@ -57,6 +57,12 @@ public: }; void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode); + enum OptionsAfterPositionalArgumentsMode { + ParseAsOptions, + ParseAsPositionalArguments + }; + void setOptionsAfterPositionalArgumentsMode(OptionsAfterPositionalArgumentsMode mode); + bool addOption(const QCommandLineOption &commandLineOption); bool addOptions(const QList<QCommandLineOption> &options); diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index ead85e9da0..6f4ebcf420 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -58,7 +58,7 @@ public: buffers.append(QByteArray()); } - inline int nextDataBlockSize() const { + inline qint64 nextDataBlockSize() const { return (tailBuffer == 0 ? tail : buffers.first().size()) - head; } @@ -86,9 +86,9 @@ public: return 0; } - inline void free(int bytes) { + inline void free(qint64 bytes) { while (bytes > 0) { - int blockSize = buffers.first().size() - head; + const qint64 blockSize = buffers.first().size() - head; if (tailBuffer == 0 || blockSize > bytes) { // keep a single block around if it does not exceed @@ -102,7 +102,8 @@ public: clear(); // try to minify/squeeze us } } else { - head += bytes; + Q_ASSERT(quint64(bytes) < QByteArray::MaxSize); + head += int(bytes); bufferSize -= bytes; } return; @@ -116,13 +117,15 @@ public: } } - inline char *reserve(int bytes) { - if (bytes <= 0) + inline char *reserve(qint64 bytes) { + if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize) return 0; + const qint64 newSize = bytes + tail; // if need buffer reallocation - if (tail + bytes > buffers.last().size()) { - if (tail + bytes > buffers.last().capacity() && tail >= basicBlockSize) { + if (newSize > buffers.last().size()) { + if (newSize > buffers.last().capacity() && (tail >= basicBlockSize + || quint64(newSize) >= QByteArray::MaxSize)) { // shrink this buffer to its current size buffers.last().resize(tail); @@ -131,21 +134,22 @@ public: ++tailBuffer; tail = 0; } - buffers.last().resize(qMax(basicBlockSize, tail + bytes)); + buffers.last().resize(qMax(basicBlockSize, tail + int(bytes))); } char *writePtr = buffers.last().data() + tail; bufferSize += bytes; - tail += bytes; + Q_ASSERT(quint64(bytes) < QByteArray::MaxSize); + tail += int(bytes); return writePtr; } - inline void truncate(int pos) { + inline void truncate(qint64 pos) { if (pos < size()) chop(size() - pos); } - inline void chop(int bytes) { + inline void chop(qint64 bytes) { while (bytes > 0) { if (tailBuffer == 0 || tail > bytes) { // keep a single block around if it does not exceed @@ -159,7 +163,8 @@ public: clear(); // try to minify/squeeze us } } else { - tail -= bytes; + Q_ASSERT(quint64(bytes) < QByteArray::MaxSize); + tail -= int(bytes); bufferSize -= bytes; } return; @@ -206,7 +211,7 @@ public: ++bufferSize; } - inline int size() const { + inline qint64 size() const { return bufferSize; } @@ -219,9 +224,9 @@ public: bufferSize = 0; } - inline int indexOf(char c) const { - int index = 0; - int j = head; + inline qint64 indexOf(char c) const { + qint64 index = 0; + qint64 j = head; for (int i = 0; i < buffers.size(); ++i) { const char *ptr = buffers[i].constData() + j; j = index + (i == tailBuffer ? tail : buffers[i].size()) - j; @@ -236,9 +241,9 @@ public: return -1; } - inline int indexOf(char c, int maxLength) const { - int index = 0; - int j = head; + inline qint64 indexOf(char c, qint64 maxLength) const { + qint64 index = 0; + qint64 j = head; for (int i = 0; index < maxLength && i < buffers.size(); ++i) { const char *ptr = buffers[i].constData() + j; j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength); @@ -253,11 +258,12 @@ public: return -1; } - inline int read(char *data, int maxLength) { - int bytesToRead = qMin(size(), maxLength); - int readSoFar = 0; + inline qint64 read(char *data, qint64 maxLength) { + const qint64 bytesToRead = qMin(size(), maxLength); + qint64 readSoFar = 0; while (readSoFar < bytesToRead) { - int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize()); + const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, + nextDataBlockSize()); if (data) memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock); readSoFar += bytesToReadFromThisBlock; @@ -300,15 +306,15 @@ public: bufferSize += tail; } - inline int skip(int length) { + inline qint64 skip(qint64 length) { return read(0, length); } - inline int readLine(char *data, int maxLength) { + inline qint64 readLine(char *data, qint64 maxLength) { if (!data || --maxLength <= 0) return -1; - int i = indexOf('\n', maxLength); + qint64 i = indexOf('\n', maxLength); i = read(data, i >= 0 ? (i + 1) : maxLength); // Terminate it. @@ -325,7 +331,7 @@ private: int head, tail; int tailBuffer; // always buffers.size() - 1 const int basicBlockSize; - int bufferSize; + qint64 bufferSize; }; QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index e74a8eebee..8998b22be8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -7600,86 +7600,155 @@ static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999) return -1; } +/* + Algorithm for multiArg: + + 1. Parse the string as a sequence of verbatim text and placeholders (%L?\d{,3}). + The L is parsed and accepted for compatibility with non-multi-arg, but since + multiArg only accepts strings as replacements, the localization request can + be safely ignored. + 2. The result of step (1) is a list of (string-ref,int)-tuples. The string-ref + either points at text to be copied verbatim (in which case the int is -1), + or, initially, at the textual representation of the placeholder. In that case, + the int contains the numerical number as parsed from the placeholder. + 3. Next, collect all the non-negative ints found, sort them in ascending order and + remove duplicates. + 3a. If the result has more entires than multiArg() was given replacement strings, + we have found placeholders we can't satisfy with replacement strings. That is + fine (there could be another .arg() call coming after this one), so just + truncate the result to the number of actual multiArg() replacement strings. + 3b. If the result has less entries than multiArg() was given replacement strings, + the string is missing placeholders. This is an error that the user should be + warned about. + 4. The result of step (3) is a mapping from the index of any replacement string to + placeholder number. This is the wrong way around, but since placeholder + numbers could get as large as 999, while we typically don't have more than 9 + replacement strings, we trade 4K of sparsely-used memory for doing a reverse lookup + each time we need to map a placeholder number to a replacement string index + (that's a linear search; but still *much* faster than using an associative container). + 5. Next, for each of the tuples found in step (1), do the following: + 5a. If the int is negative, do nothing. + 5b. Otherwise, if the int is found in the result of step (3) at index I, replace + the string-ref with a string-ref for the (complete) I'th replacement string. + 5c. Otherwise, do nothing. + 6. Concatenate all string refs into a single result string. +*/ + namespace { -class ArgMapper { - QVarLengthArray<int, 16> argPosToNumberMap; // maps from argument position to number -public: - void found(int n) { argPosToNumberMap.push_back(n); } +struct Part +{ + Part() : stringRef(), number(0) {} + Part(const QString &s, int pos, int len, int num = -1) Q_DECL_NOTHROW + : stringRef(&s, pos, len), number(num) {} - struct AssignmentResult { - int numArgs; - int lastNumber; - }; + QStringRef stringRef; + int number; +}; +} // unnamed namespace - AssignmentResult assignArgumentNumberToEachOfTheNs(int numArgs) - { - std::sort(argPosToNumberMap.begin(), argPosToNumberMap.end()); - argPosToNumberMap.erase(std::unique(argPosToNumberMap.begin(), argPosToNumberMap.end()), - argPosToNumberMap.end()); +template <> +class QTypeInfo<Part> : public QTypeInfoMerger<Part, QStringRef, int> {}; // Q_DECLARE_METATYPE - if (argPosToNumberMap.size() > numArgs) - argPosToNumberMap.resize(numArgs); - int lastNumber = argPosToNumberMap.empty() ? -1 : argPosToNumberMap.back(); - int arg = argPosToNumberMap.size(); +namespace { - const AssignmentResult result = {arg, lastNumber}; - return result; - } +enum { ExpectedParts = 32 }; - int numberToArgsIndex(int number) const - { - if (number != -1) { - const int * const it = std::find(argPosToNumberMap.begin(), argPosToNumberMap.end(), number); - return it == argPosToNumberMap.end() ? -1 : it - argPosToNumberMap.begin(); - } else { - return -1; - } - } -}; -} // unnamed namespace +typedef QVarLengthArray<Part, ExpectedParts> ParseResult; +typedef QVarLengthArray<int, ExpectedParts/2> ArgIndexToPlaceholderMap; -QString QString::multiArg(int numArgs, const QString **args) const +static ParseResult parseMultiArgFormatString(const QString &s) { - QString result; - ArgMapper mapper; - const QChar *uc = (const QChar *) d->data(); - const int len = d->size; + ParseResult result; + + const QChar *uc = s.constData(); + const int len = s.size(); const int end = len - 1; int i = 0; + int last = 0; - // populate the arg-mapper with the %n's that actually occur in the string while (i < end) { if (uc[i] == QLatin1Char('%')) { + int percent = i; int number = getEscape(uc, &i, len); if (number != -1) { - mapper.found(number); + if (last != percent) + result.push_back(Part(s, last, percent - last)); // literal text (incl. failed placeholders) + result.push_back(Part(s, percent, i - percent, number)); // parsed placeholder + last = i; continue; } } ++i; } - const ArgMapper::AssignmentResult r = mapper.assignArgumentNumberToEachOfTheNs(numArgs); + if (last < len) + result.push_back(Part(s, last, len - last)); // trailing literal text + + return result; +} - // sanity - if (numArgs > r.numArgs) { - qWarning("QString::arg: %d argument(s) missing in %s", numArgs - r.numArgs, toLocal8Bit().data()); - numArgs = r.numArgs; +static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult &parts) +{ + ArgIndexToPlaceholderMap result; + + for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) { + if (it->number >= 0) + result.push_back(it->number); } - i = 0; - while (i < len) { - if (uc[i] == QLatin1Char('%') && i != end) { - int number = getEscape(uc, &i, len, r.lastNumber); - int arg = mapper.numberToArgsIndex(number); - if (number != -1 && arg != -1) { - result += *args[arg]; - continue; - } + std::sort(result.begin(), result.end()); + result.erase(std::unique(result.begin(), result.end()), + result.end()); + + return result; +} + +static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[]) +{ + int totalSize = 0; + for (ParseResult::iterator pit = parts.begin(), end = parts.end(); pit != end; ++pit) { + if (pit->number != -1) { + const ArgIndexToPlaceholderMap::const_iterator ait + = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), pit->number); + if (ait != argIndexToPlaceholderMap.end()) + pit->stringRef = QStringRef(args[ait - argIndexToPlaceholderMap.begin()]); } - result += uc[i++]; + totalSize += pit->stringRef.size(); } + return totalSize; +} + +} // unnamed namespace + +QString QString::multiArg(int numArgs, const QString **args) const +{ + // Step 1-2 above + ParseResult parts = parseMultiArgFormatString(*this); + + // 3-4 + ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts); + + if (argIndexToPlaceholderMap.size() > numArgs) // 3a + argIndexToPlaceholderMap.resize(numArgs); + else if (argIndexToPlaceholderMap.size() < numArgs) // 3b + qWarning("QString::arg: %d argument(s) missing in %s", + numArgs - argIndexToPlaceholderMap.size(), toLocal8Bit().data()); + + // 5 + const int totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args); + + // 6: + QString result(totalSize, Qt::Uninitialized); + QChar *out = result.data(); + + for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) { + if (const int sz = it->stringRef.size()) { + memcpy(out, it->stringRef.constData(), sz * sizeof(QChar)); + out += sz; + } + } + return result; } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 9d5b749e79..a48269cfaa 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -265,7 +265,6 @@ private: { return (i <= d->end()) && (d->begin() <= i); } - iterator c2m(const_iterator it) { return begin() + (it - cbegin()); } class AlignmentDummy { Data header; T array[1]; }; }; |