diff options
Diffstat (limited to 'src/corelib/kernel')
22 files changed, 596 insertions, 1018 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index bc93791c2e..adcc9c5581 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -143,8 +143,14 @@ unix|integrity { kernel/qcore_unix_p.h \ kernel/qcrashhandler_p.h \ kernel/qeventdispatcher_unix_p.h \ + kernel/qpoll_p.h \ kernel/qtimerinfo_unix_p.h + contains(QT_CONFIG, poll_select): SOURCES += kernel/qpoll.cpp + contains(QT_CONFIG, poll_poll): DEFINES += QT_HAVE_POLL + contains(QT_CONFIG, poll_ppoll): DEFINES += QT_HAVE_POLL QT_HAVE_PPOLL + contains(QT_CONFIG, poll_pollts): DEFINES += QT_HAVE_POLL QT_HAVE_POLLTS + contains(QT_CONFIG, glib) { SOURCES += \ kernel/qeventdispatcher_glib.cpp @@ -176,13 +182,6 @@ vxworks { kernel/qfunctions_vxworks.h } -blackberry { - SOURCES += \ - kernel/qeventdispatcher_blackberry.cpp - HEADERS += \ - kernel/qeventdispatcher_blackberry_p.h -} - qqnx_pps { LIBS_PRIVATE += -lpps SOURCES += \ diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp index 9892cc7333..66bfa415a7 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.cpp +++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp @@ -92,9 +92,6 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter() On Mac, \a eventType is set to "mac_generic_NSEvent", and the \a message can be casted to an EventRef. - On Blackberry (not plain QNX) \a eventType is set to "bps_event_t", and the \a message can be casted - to a bps_event_t pointer. - In your reimplementation of this function, if you want to filter the \a message out, i.e. stop it being handled further, return true; otherwise return false. diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 5695cb3ec5..97c0efc36f 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -50,12 +50,13 @@ #include <mach/mach_time.h> #endif -#ifdef Q_OS_BLACKBERRY -#include <qsocketnotifier.h> -#endif // Q_OS_BLACKBERRY - QT_BEGIN_NAMESPACE +#if !defined(QT_HAVE_PPOLL) && defined(QT_HAVE_POLLTS) +# define ppoll pollts +# define QT_HAVE_PPOLL +#endif + static inline bool time_update(struct timespec *tv, const struct timespec &start, const struct timespec &timeout) { @@ -85,9 +86,7 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, #ifndef Q_OS_QNX ret = ::pselect(nfds, fdread, fdwrite, fdexcept, &timeout, 0); #else - timeval timeoutVal; - timeoutVal.tv_sec = timeout.tv_sec; - timeoutVal.tv_usec = timeout.tv_nsec / 1000; + timeval timeoutVal = timespecToTimeval(timeout); ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeoutVal); #endif if (ret != -1 || errno != EINTR) @@ -102,43 +101,80 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, } } +static inline struct timespec millisecsToTimespec(const unsigned int ms) +{ + struct timespec tv; + + tv.tv_sec = ms / 1000; + tv.tv_nsec = (ms % 1000) * 1000 * 1000; + + return tv; +} + int qt_select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) { if (timeout < 0) return qt_safe_select(nfds, fdread, fdwrite, 0, 0); - struct timespec tv; - tv.tv_sec = timeout / 1000; - tv.tv_nsec = (timeout % 1000) * 1000 * 1000; + struct timespec tv = millisecsToTimespec(timeout); return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); } -#ifdef Q_OS_BLACKBERRY -// The BlackBerry event dispatcher uses bps_get_event. Unfortunately, already registered -// socket notifiers are disabled by a call to select. This is to rearm the standard streams. -int bb_select(QList<QSocketNotifier *> socketNotifiers, int nfds, fd_set *fdread, fd_set *fdwrite, - int timeout) +#if !defined(QT_HAVE_PPOLL) && defined(QT_HAVE_POLL) +static inline int timespecToMillisecs(const struct timespec *ts) { - QList<bool> socketNotifiersEnabled; - socketNotifiersEnabled.reserve(socketNotifiers.count()); - for (int a = 0; a < socketNotifiers.count(); ++a) { - if (socketNotifiers.at(a) && socketNotifiers.at(a)->isEnabled()) { - socketNotifiersEnabled.append(true); - socketNotifiers.at(a)->setEnabled(false); - } else { - socketNotifiersEnabled.append(false); - } - } + return (ts == NULL) ? -1 : + (ts->tv_sec * 1000) + (ts->tv_nsec / 1000000); +} +#endif + +// defined in qpoll.cpp +int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts); + +static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts) +{ +#if defined(QT_HAVE_PPOLL) + return ::ppoll(fds, nfds, timeout_ts, Q_NULLPTR); +#elif defined(QT_HAVE_POLL) + return ::poll(fds, nfds, timespecToMillisecs(timeout_ts)); +#else + return qt_poll(fds, nfds, timeout_ts); +#endif +} + - const int ret = qt_select_msecs(nfds, fdread, fdwrite, timeout); +/*! + \internal - for (int a = 0; a < socketNotifiers.count(); ++a) { - if (socketNotifiersEnabled.at(a) == true) - socketNotifiers.at(a)->setEnabled(true); + Behaves as close to POSIX poll(2) as practical but may be implemented + using select(2) where necessary. In that case, returns -1 and sets errno + to EINVAL if passed any descriptor greater than or equal to FD_SETSIZE. +*/ +int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts) +{ + if (!timeout_ts) { + // no timeout -> block forever + int ret; + EINTR_LOOP(ret, qt_ppoll(fds, nfds, Q_NULLPTR)); + return ret; } - return ret; + timespec start = qt_gettime(); + timespec timeout = *timeout_ts; + + // loop and recalculate the timeout as needed + forever { + const int ret = qt_ppoll(fds, nfds, &timeout); + if (ret != -1 || errno != EINTR) + return ret; + + // recalculate the timeout + if (!time_update(&timeout, start, *timeout_ts)) { + // timeout during update + // or clock reset, fake timeout error + return 0; + } + } } -#endif // Q_OS_BLACKBERRY QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index f80dcb5a50..fcc65589a0 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -66,6 +66,12 @@ # include <ioLib.h> #endif +#ifdef QT_NO_NATIVE_POLL +# include "qpoll_p.h" +#else +# include <poll.h> +#endif + struct sockaddr; #define EINTR_LOOP(var, cmd) \ @@ -121,6 +127,14 @@ inline timespec operator*(const timespec &t1, int mul) tmp.tv_nsec = t1.tv_nsec * mul; return normalizedTimespec(tmp); } +inline timeval timespecToTimeval(const timespec &ts) +{ + timeval tv; + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; +} + inline void qt_ignore_sigpipe() { @@ -303,17 +317,13 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) timespec qt_gettime() Q_DECL_NOTHROW; void qt_nanosleep(timespec amount); +Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts); + Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timespec *tv); int qt_select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout); -#ifdef Q_OS_BLACKBERRY -class QSocketNotifier; -Q_CORE_EXPORT int bb_select(QList<QSocketNotifier *> socketNotifiers, int nfds, fd_set *fdread, - fd_set *fdwrite, int timeout); -#endif // Q_OS_BLACKBERRY - // according to X/OPEN we have to define semun ourselves // we use prefix as on some systems sem.h will have it struct semid_ds; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index abc5af94cb..8d9b923e61 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -66,19 +66,14 @@ #ifndef QT_NO_QOBJECT #if defined(Q_OS_UNIX) -# if defined(Q_OS_BLACKBERRY) -# include "qeventdispatcher_blackberry_p.h" -# include <process.h> -# include <unistd.h> -# elif defined(Q_OS_OSX) -# include "qeventdispatcher_cf_p.h" -# include "qeventdispatcher_unix_p.h" -# else -# if !defined(QT_NO_GLIB) -# include "qeventdispatcher_glib_p.h" -# endif -# include "qeventdispatcher_unix_p.h" +# if defined(Q_OS_OSX) +# include "qeventdispatcher_cf_p.h" +# else +# if !defined(QT_NO_GLIB) +# include "qeventdispatcher_glib_p.h" # endif +# endif +# include "qeventdispatcher_unix_p.h" #endif #ifdef Q_OS_WIN # ifdef Q_OS_WINRT @@ -338,34 +333,6 @@ struct QCoreApplicationData { #endif } -#ifdef Q_OS_BLACKBERRY - //The QCoreApplicationData struct is only populated on demand, because it is rarely needed and would - //affect startup time - void loadManifest() { - static bool manifestLoadAttempt = false; - if (manifestLoadAttempt) - return; - - manifestLoadAttempt = true; - - QFile metafile(QStringLiteral("app/META-INF/MANIFEST.MF")); - if (!metafile.open(QIODevice::ReadOnly)) { - qWarning("Could not open application metafile for reading") - } else { - while (!metafile.atEnd() && (application.isEmpty() || applicationVersion.isEmpty() || orgName.isEmpty())) { - QByteArray line = metafile.readLine(); - if (line.startsWith("Application-Name:")) - application = QString::fromUtf8(line.mid(18).trimmed()); - else if (line.startsWith("Application-Version:")) - applicationVersion = QString::fromUtf8(line.mid(21).trimmed()); - else if (line.startsWith("Package-Author:")) - orgName = QString::fromUtf8(line.mid(16).trimmed()); - } - metafile.close(); - } - } -#endif - QString orgName, orgDomain; QString application; // application name, initially from argv[0], can then be modified. QString applicationVersion; @@ -450,7 +417,7 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::is_app_closing = false; # if defined(Q_OS_UNIX) - if (!setuidAllowed && (geteuid() != getuid())) + if (Q_UNLIKELY(!setuidAllowed && (geteuid() != getuid()))) qFatal("FATAL: The application binary appears to be running setuid, this is a security hole."); # endif // Q_OS_UNIX @@ -506,9 +473,7 @@ void QCoreApplicationPrivate::createEventDispatcher() { Q_Q(QCoreApplication); #if defined(Q_OS_UNIX) -# if defined(Q_OS_BLACKBERRY) - eventDispatcher = new QEventDispatcherBlackberry(q); -# elif defined(Q_OS_OSX) +# if defined(Q_OS_OSX) bool ok = false; int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); if (ok && value > 0) @@ -600,7 +565,7 @@ void QCoreApplicationPrivate::initLocale() if (qt_locale_initialized) return; qt_locale_initialized = true; -#ifdef Q_OS_UNIX +#if defined(Q_OS_UNIX) && !defined(QT_BOOTSTRAPPED) setlocale(LC_ALL, ""); #endif } @@ -2135,33 +2100,6 @@ QString QCoreApplication::applicationFilePath() #if defined(Q_OS_WIN) QCoreApplicationPrivate::setApplicationFilePath(QFileInfo(qAppFileName()).filePath()); return *QCoreApplicationPrivate::cachedApplicationFilePath; -#elif defined(Q_OS_BLACKBERRY) - if (!arguments().isEmpty()) { // args is never empty, but the navigator can change behaviour some day - QFileInfo fileInfo(arguments().at(0)); - const bool zygotized = fileInfo.exists(); - if (zygotized) { - // Handle the zygotized case: - QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(fileInfo.absoluteFilePath())); - return *QCoreApplicationPrivate::cachedApplicationFilePath; - } - } - - // Handle the non-zygotized case: - const size_t maximum_path = static_cast<size_t>(pathconf("/",_PC_PATH_MAX)); - char buff[maximum_path+1]; - if (_cmdname(buff)) { - QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(QString::fromLocal8Bit(buff))); - } else { - qWarning("QCoreApplication::applicationFilePath: _cmdname() failed"); - // _cmdname() won't fail, but just in case, fallback to the old method - QDir dir(QStringLiteral("./app/native/")); - QStringList executables = dir.entryList(QDir::Executable | QDir::Files); - if (!executables.empty()) { - //We assume that there is only one executable in the folder - QCoreApplicationPrivate::setApplicationFilePath(dir.absoluteFilePath(executables.first())); - } - } - return *QCoreApplicationPrivate::cachedApplicationFilePath; #elif defined(Q_OS_MAC) QString qAppFileName_str = qAppFileName(); if(!qAppFileName_str.isEmpty()) { @@ -2327,9 +2265,6 @@ QStringList QCoreApplication::arguments() organizationName(). On all other platforms, QSettings uses organizationName() as the organization. - On BlackBerry this property is read-only. It is obtained from the - BAR application descriptor file. - \sa organizationDomain, applicationName */ @@ -2354,9 +2289,6 @@ void QCoreApplication::setOrganizationName(const QString &orgName) QString QCoreApplication::organizationName() { -#ifdef Q_OS_BLACKBERRY - coreappdata()->loadManifest(); -#endif return coreappdata()->orgName; } @@ -2407,9 +2339,6 @@ QString QCoreApplication::organizationDomain() If not set, the application name defaults to the executable name (since 5.0). - On BlackBerry this property is read-only. It is obtained from the - BAR application descriptor file. - \sa organizationName, organizationDomain, applicationVersion, applicationFilePath() */ /*! @@ -2435,9 +2364,6 @@ void QCoreApplication::setApplicationName(const QString &application) QString QCoreApplication::applicationName() { -#ifdef Q_OS_BLACKBERRY - coreappdata()->loadManifest(); -#endif return coreappdata() ? coreappdata()->application : QString(); } @@ -2452,9 +2378,6 @@ Q_CORE_EXPORT QString qt_applicationName_noFallback() \since 4.4 \brief the version of this application - On BlackBerry this property is read-only. It is obtained from the - BAR application descriptor file. - \sa applicationName, organizationName, organizationDomain */ /*! @@ -2476,9 +2399,6 @@ void QCoreApplication::setApplicationVersion(const QString &version) QString QCoreApplication::applicationVersion() { -#ifdef Q_OS_BLACKBERRY - coreappdata()->loadManifest(); -#endif return coreappdata()->applicationVersion; } @@ -2698,7 +2618,7 @@ void QCoreApplication::removeLibraryPath(const QString &path) i.e. MSG or XCB event structs. \note Native event filters will be disabled in the application when the - Qt::AA_MacPluginApplication attribute is set. + Qt::AA_PluginApplication attribute is set. For maximum portability, you should always try to use QEvent and QObject::installEventFilter() whenever possible. @@ -2709,8 +2629,8 @@ void QCoreApplication::removeLibraryPath(const QString &path) */ void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj) { - if (QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) { - qWarning("Native event filters are not applied when the Qt::AA_MacPluginApplication attribute is set"); + if (QCoreApplication::testAttribute(Qt::AA_PluginApplication)) { + qWarning("Native event filters are not applied when the Qt::AA_PluginApplication attribute is set"); return; } diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 53da4a849b..d9de828fa1 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -276,6 +276,8 @@ public: PlatformSurface = 217, // Platform surface created or about to be destroyed + Pointer = 218, // QQuickPointerEvent; ### Qt 6: QPointerEvent + // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp deleted file mode 100644 index a8e3d3c766..0000000000 --- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qeventdispatcher_blackberry_p.h" -#include "qsocketnotifier.h" -#include "qdebug.h" -#include "qelapsedtimer.h" -#include "private/qthread_p.h" - -#include <bps/bps.h> -#include <bps/event.h> - -//#define QEVENTDISPATCHERBLACKBERRY_DEBUG - -#ifdef QEVENTDISPATCHERBLACKBERRY_DEBUG -#include <QThread> -#define qEventDispatcherDebug qDebug() << QThread::currentThread() -#else -#define qEventDispatcherDebug QT_NO_QDEBUG_MACRO() -#endif - -QT_BEGIN_NAMESPACE - -class BpsChannelScopeSwitcher -{ -public: - BpsChannelScopeSwitcher(int scopeChannel) : innerChannel(scopeChannel) - { - outerChannel = bps_channel_get_active(); - if (outerChannel != innerChannel) - bps_channel_set_active(innerChannel); - } - - ~BpsChannelScopeSwitcher() - { - if (outerChannel != innerChannel) - bps_channel_set_active(outerChannel); - } - -private: - int innerChannel; - int outerChannel; -}; - -class BBScopedLoopLevelCounter -{ - QEventDispatcherBlackberryPrivate *d; - -public: - inline BBScopedLoopLevelCounter(QEventDispatcherBlackberryPrivate *p) - : d(p) - { ++d->loop_level; } - - inline ~BBScopedLoopLevelCounter() - { --d->loop_level; } -}; - -struct bpsIOHandlerData -{ - bpsIOHandlerData() - : count(0), readfds(0), writefds(0), exceptfds(0) - { - } - - int count; - fd_set *readfds; - fd_set *writefds; - fd_set *exceptfds; -}; - -static int bpsUnblockDomain = -1; - -static int bpsIOHandler(int fd, int io_events, void *data) -{ - qEventDispatcherDebug; - // decode callback payload - bpsIOHandlerData *ioData = static_cast<bpsIOHandlerData*>(data); - - // check if first file is ready - bool firstReady = (ioData->count == 0); - - // update ready state of file - if (io_events & BPS_IO_INPUT) { - qEventDispatcherDebug << fd << "ready for Read"; - FD_SET(fd, ioData->readfds); - ioData->count++; - } - - if (io_events & BPS_IO_OUTPUT) { - qEventDispatcherDebug << fd << "ready for Write"; - FD_SET(fd, ioData->writefds); - ioData->count++; - } - - if (io_events & BPS_IO_EXCEPT) { - qEventDispatcherDebug << fd << "ready for Exception"; - FD_SET(fd, ioData->exceptfds); - ioData->count++; - } - - // force bps_get_event() to return immediately by posting an event to ourselves; - // but this only needs to happen once if multiple files become ready at the same time - if (firstReady) { - qEventDispatcherDebug << "Sending bpsIOReadyDomain event"; - // create unblock event - bps_event_t *event; - int result = bps_event_create(&event, bpsUnblockDomain, 0, NULL, NULL); - if (Q_UNLIKELY(result != BPS_SUCCESS)) { - qWarning("QEventDispatcherBlackberry: bps_event_create failed"); - return BPS_FAILURE; - } - - // post unblock event to our thread; in this callback the bps channel is - // guaranteed to be the same that was active when bps_add_fd was called - result = bps_push_event(event); - if (Q_UNLIKELY(result != BPS_SUCCESS)) { - qWarning("QEventDispatcherBlackberry: bps_push_event failed"); - bps_event_destroy(event); - return BPS_FAILURE; - } - } - - return BPS_SUCCESS; -} - -QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberryPrivate() - : loop_level(0) - , ioData(new bpsIOHandlerData) -{ - // prepare to use BPS - int result = bps_initialize(); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qFatal("QEventDispatcherBlackberry: bps_initialize failed"); - - bps_channel = bps_channel_get_active(); - - if (bps_channel_create(&holding_channel, 0) != BPS_SUCCESS) { - qWarning("QEventDispatcherBlackberry: bps_channel_create failed"); - holding_channel = -1; - } - - // get domain for IO ready and wake up events - ignoring race condition here for now - if (bpsUnblockDomain == -1) { - bpsUnblockDomain = bps_register_domain(); - if (Q_UNLIKELY(bpsUnblockDomain == -1)) - qWarning("QEventDispatcherBlackberry: bps_register_domain failed"); - } -} - -QEventDispatcherBlackberryPrivate::~QEventDispatcherBlackberryPrivate() -{ - if ((holding_channel != -1) && - (bps_channel_destroy(holding_channel) != BPS_SUCCESS)) { - qWarning("QEventDispatcherBlackberry: bps_channel_destroy failed"); - } - - // we're done using BPS - bps_shutdown(); -} - -int QEventDispatcherBlackberryPrivate::initThreadWakeUp() -{ - return -1; // no fd's used -} - -int QEventDispatcherBlackberryPrivate::processThreadWakeUp(int nsel) -{ - Q_UNUSED(nsel); - return wakeUps.fetchAndStoreRelaxed(0); -} - -///////////////////////////////////////////////////////////////////////////// - -QEventDispatcherBlackberry::QEventDispatcherBlackberry(QObject *parent) - : QEventDispatcherUNIX(*new QEventDispatcherBlackberryPrivate, parent) -{ -} - -QEventDispatcherBlackberry::QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent) - : QEventDispatcherUNIX(dd, parent) -{ -} - -QEventDispatcherBlackberry::~QEventDispatcherBlackberry() -{ -} - -void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifier) -{ - Q_ASSERT(notifier); - Q_D(QEventDispatcherBlackberry); - - int sockfd = notifier->socket(); - int type = notifier->type(); - - qEventDispatcherDebug << "fd =" << sockfd; - - if (Q_UNLIKELY(sockfd >= FD_SETSIZE)) { - qWarning() << "QEventDispatcherBlackberry: cannot register QSocketNotifier (fd too high)" - << sockfd; - return; - } - - // Register the fd with bps - BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); - int io_events = ioEvents(sockfd); - if (io_events) - bps_remove_fd(sockfd); - - switch (type) { - case QSocketNotifier::Read: - qEventDispatcherDebug << "Registering" << sockfd << "for Reads"; - io_events |= BPS_IO_INPUT; - break; - case QSocketNotifier::Write: - qEventDispatcherDebug << "Registering" << sockfd << "for Writes"; - io_events |= BPS_IO_OUTPUT; - break; - case QSocketNotifier::Exception: - default: - qEventDispatcherDebug << "Registering" << sockfd << "for Exceptions"; - io_events |= BPS_IO_EXCEPT; - break; - } - - const int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qWarning() << "QEventDispatcherBlackberry: bps_add_fd failed"; - - // Call the base Unix implementation. Needed to allow select() to be called correctly - QEventDispatcherUNIX::registerSocketNotifier(notifier); -} - -void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier) -{ - Q_D(QEventDispatcherBlackberry); - - int sockfd = notifier->socket(); - - qEventDispatcherDebug << "fd =" << sockfd; - - if (Q_UNLIKELY(sockfd >= FD_SETSIZE)) { - qWarning() << "QEventDispatcherBlackberry: cannot unregister QSocketNotifier" << sockfd; - return; - } - - // Allow the base Unix implementation to unregister the fd too (before call to ioEvents()!) - QEventDispatcherUNIX::unregisterSocketNotifier(notifier); - - // Unregister the fd with bps - BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); - int result = bps_remove_fd(sockfd); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qWarning() << "QEventDispatcherBlackberry: bps_remove_fd failed" << sockfd; - - const int io_events = ioEvents(sockfd); - // if other socket notifier is watching sockfd, readd it - if (io_events) { - result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qWarning("QEventDispatcherBlackberry: bps_add_fd error"); - } -} - -static inline int timespecToMillisecs(const timespec &tv) -{ - return (tv.tv_sec * 1000) + (tv.tv_nsec / 1000000); -} - -static inline void destroyHeldBpsEvent(int holding_channel) -{ - // Switch to the holding channel and use bps_get_event() to trigger its destruction. We - // don't care about the return value from this call to bps_get_event(). - BpsChannelScopeSwitcher holdingChannelSwitcher(holding_channel); - bps_event_t *held_event = 0; - (void)bps_get_event(&held_event, 0); - } - -int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - timespec *timeout) -{ - Q_UNUSED(nfds); - Q_D(QEventDispatcherBlackberry); - const BBScopedLoopLevelCounter bbLoopCounter(d); - - BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); - - // prepare file sets for bps callback - d->ioData->count = 0; - d->ioData->readfds = readfds; - d->ioData->writefds = writefds; - d->ioData->exceptfds = exceptfds; - - // reset all file sets - if (readfds) - FD_ZERO(readfds); - - if (writefds) - FD_ZERO(writefds); - - if (exceptfds) - FD_ZERO(exceptfds); - - bps_event_t *event = 0; - unsigned int eventCount = 0; - - // If an event handler called through filterEvent() starts a nested event loop by creating a - // new QEventLoop, we will recursively enter this function again. However, each time - // bps_get_event() is called, it destroys the last event it handed out before returning the - // next event. We don't want it to destroy the event that triggered the nested event loop, - // since there may still be more handlers that need to get that event, once the nested event - // loop is done and control returns to the outer event loop. - // - // So we move an event to a holding channel, which takes ownership of the event. Putting - // the event on our own channel allows us to manage when it is destroyed, keeping it alive - // until we know we are done with it. Each recursive call of this function needs to have - // it's own holding channel, since a channel is a queue, not a stack. - // - // However, a recursive call into this function happens very rarely compared to the many - // times this function is called. We don't want to create a holding channel for each time - // this function is called, only when it is called recursively. Thus we have the instance - // variable d->holding_channel to use in the common case. We keep track of recursive calls - // with d->loop_level. If we are in a recursive call, then we create a new holding channel - // for this run. - int holding_channel = d->holding_channel; - if ((d->loop_level > 1) && - Q_UNLIKELY(bps_channel_create(&holding_channel, 0) != BPS_SUCCESS)) { - qWarning("QEventDispatcherBlackberry: bps_channel_create failed"); - holding_channel = -1; - } - - // Convert timeout to milliseconds - int timeoutTotal = -1; - if (timeout) - timeoutTotal = timespecToMillisecs(*timeout); - int timeoutLeft = timeoutTotal; - timespec startTime = qt_gettime(); - - // This loop exists such that we can drain the bps event queue of all native events - // more efficiently than if we were to return control to Qt after each event. This - // is important for handling touch events which can come in rapidly. - forever { - // Only emit the awake() and aboutToBlock() signals in the second iteration. For the - // first iteration, the UNIX event dispatcher will have taken care of that already. - // Also native events are actually processed one loop iteration after they were - // retrieved with bps_get_event(). - - // Filtering the native event should happen between the awake() and aboutToBlock() - // signal emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - - // bps_get_event() need not to be interrupted by a break or return statement. - if (eventCount > 0) { - if (event) { - emit awake(); - filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); - emit aboutToBlock(); - - if (Q_LIKELY(holding_channel != -1)) { - // We are now done with this BPS event. Destroy it. - destroyHeldBpsEvent(holding_channel); - } - } - - // Update the timeout - // Clock source is monotonic, so we can recalculate how much timeout is left - if (timeoutTotal != -1) { - timespec t2 = qt_gettime(); - timeoutLeft = timeoutTotal - - (timespecToMillisecs(t2) - timespecToMillisecs(startTime)); - if (timeoutLeft < 0) - timeoutLeft = 0; - } - - timespec tnext; - if (d->timerList.timerWait(tnext)) { - int timeoutNext = timespecToMillisecs(tnext); - if (timeoutNext < timeoutLeft || timeoutTotal == -1) { - timeoutTotal = timeoutLeft = timeoutNext; - startTime = qt_gettime(); - } - } - } - - event = 0; - { // We need to increase loop level in this scope, - // because bps_get_event can also invoke callbacks - QScopedLoopLevelCounter loopLevelCounter(d->threadData); - - // Wait for event or file to be ready - const int result = bps_get_event(&event, timeoutLeft); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qWarning("QEventDispatcherBlackberry: bps_get_event failed"); - } - - if (!event) // In case of !event, we break out of the loop to let Qt process the timers - break; // (since timeout has expired) and socket notifiers that are now ready. - - if (bps_event_get_domain(event) == bpsUnblockDomain) { - timeoutTotal = 0; // in order to immediately drain the event queue of native events - event = 0; // (especially touch move events) we don't break out here - } else { - // Move the event to our holding channel so we can manage when it is destroyed. - if (Q_LIKELY(holding_channel != 1) && - Q_UNLIKELY(bps_channel_push_event(holding_channel, event) != BPS_SUCCESS)) { - qWarning("QEventDispatcherBlackberry: bps_channel_push_event failed"); - } - } - - ++eventCount; - - // Make sure we are not trapped in this loop due to continuous native events - // also we cannot recalculate the timeout without a monotonic clock as the time may have changed - const unsigned int maximumEventCount = 12; - if (Q_UNLIKELY((eventCount > maximumEventCount && timeoutLeft == 0) - || !QElapsedTimer::isMonotonic())) { - if (event) { - filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); - - if (Q_LIKELY(holding_channel != -1)) { - // We are now done with this BPS event. Destroy it. - destroyHeldBpsEvent(holding_channel); - } - } - break; - } - } - - // If this was a recursive call into this function, a new holding channel was created for - // this run, so destroy it now. - if ((holding_channel != d->holding_channel) && - Q_LIKELY(holding_channel != -1) && - Q_UNLIKELY(bps_channel_destroy(holding_channel) != BPS_SUCCESS)) { - qWarning("QEventDispatcherBlackberry: bps_channel_destroy failed"); - } - - // the number of bits set in the file sets - return d->ioData->count; -} - -void QEventDispatcherBlackberry::wakeUp() -{ - Q_D(QEventDispatcherBlackberry); - if (d->wakeUps.testAndSetAcquire(0, 1)) { - bps_event_t *event; - if (Q_LIKELY(bps_event_create(&event, bpsUnblockDomain, 0, 0, 0) == BPS_SUCCESS)) { - if (Q_LIKELY(bps_channel_push_event(d->bps_channel, event) == BPS_SUCCESS)) - return; - else - bps_event_destroy(event); - } - qWarning("QEventDispatcherBlackberry: wakeUp failed"); - } -} - -int QEventDispatcherBlackberry::ioEvents(int fd) -{ - int io_events = 0; - - Q_D(QEventDispatcherBlackberry); - - if (FD_ISSET(fd, &d->sn_vec[0].enabled_fds)) - io_events |= BPS_IO_INPUT; - - if (FD_ISSET(fd, &d->sn_vec[1].enabled_fds)) - io_events |= BPS_IO_OUTPUT; - - if (FD_ISSET(fd, &d->sn_vec[2].enabled_fds)) - io_events |= BPS_IO_EXCEPT; - - return io_events; -} - -QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 155f7b7aa2..f8102195cc 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE -#if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS) +#if defined(Q_OS_VXWORKS) static void initThreadPipeFD(int fd) { int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -87,22 +87,11 @@ static void initThreadPipeFD(int fd) QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() { - extern Qt::HANDLE qt_application_thread_id; - mainThread = (QThread::currentThreadId() == qt_application_thread_id); bool pipefail = false; // initialize the common parts of the event loop -#if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY) +#if defined(Q_OS_NACL) // do nothing. -#elif defined(Q_OS_INTEGRITY) - // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead - if (socketpair(AF_INET, SOCK_STREAM, 0, thread_pipe) == -1) { - perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); - pipefail = true; - } else { - initThreadPipeFD(thread_pipe[0]); - initThreadPipeFD(thread_pipe[1]); - } #elif defined(Q_OS_VXWORKS) char name[20]; qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf())); @@ -135,7 +124,7 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() } #endif - if (pipefail) + if (Q_UNLIKELY(pipefail)) qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); sn_highest = -1; @@ -143,7 +132,7 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { -#if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY) +#if defined(Q_OS_NACL) // do nothing. #elif defined(Q_OS_VXWORKS) close(thread_pipe[0]); diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index df080809b6..18a96c6e9a 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -86,12 +86,6 @@ public: class QEventDispatcherUNIXPrivate; -#ifdef Q_OS_QNX -# define FINAL_EXCEPT_BLACKBERRY -#else -# define FINAL_EXCEPT_BLACKBERRY Q_DECL_FINAL -#endif - class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher { Q_OBJECT @@ -104,8 +98,8 @@ public: bool processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE; bool hasPendingEvents() Q_DECL_OVERRIDE; - void registerSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY; - void unregisterSocketNotifier(QSocketNotifier *notifier) FINAL_EXCEPT_BLACKBERRY; + void registerSocketNotifier(QSocketNotifier *notifier) Q_DECL_FINAL; + void unregisterSocketNotifier(QSocketNotifier *notifier) Q_DECL_FINAL; void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) Q_DECL_FINAL; bool unregisterTimer(int timerId) Q_DECL_FINAL; @@ -114,7 +108,7 @@ public: int remainingTime(int timerId) Q_DECL_FINAL; - void wakeUp() FINAL_EXCEPT_BLACKBERRY; + void wakeUp() Q_DECL_FINAL; void interrupt() Q_DECL_FINAL; void flush() Q_DECL_OVERRIDE; @@ -140,10 +134,8 @@ public: ~QEventDispatcherUNIXPrivate(); int doSelect(QEventLoop::ProcessEventsFlags flags, timespec *timeout); - virtual int initThreadWakeUp() FINAL_EXCEPT_BLACKBERRY; - virtual int processThreadWakeUp(int nsel) FINAL_EXCEPT_BLACKBERRY; - - bool mainThread; + virtual int initThreadWakeUp() Q_DECL_FINAL; + virtual int processThreadWakeUp(int nsel) Q_DECL_FINAL; // note for eventfd(7) support: // if thread_pipe[1] is -1, then eventfd(7) is in use and is stored in thread_pipe[0] @@ -163,8 +155,6 @@ public: QAtomicInt interrupt; // bool }; -#undef FINAL_EXCEPT_BLACKBERRY - QT_END_NAMESPACE #endif // QEVENTDISPATCHER_UNIX_P_H diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index bb091e9f6d..62aaca88e9 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -667,7 +667,7 @@ void QEventDispatcherWin32::installMessageHook() #ifndef Q_OS_WINCE // setup GetMessage hook needed to drive our posted events d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId()); - if (!d->getMessageHook) { + if (Q_UNLIKELY(!d->getMessageHook)) { int errorCode = GetLastError(); qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s", errorCode, qPrintable(qt_error_string(errorCode))); diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index 021e137273..c2302cbc5e 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -36,6 +36,7 @@ #include "qobject_p.h" #include "qmetaobject_p.h" +#include <vector> #include <stdlib.h> QT_BEGIN_NAMESPACE @@ -88,7 +89,6 @@ static inline Q_DECL_UNUSED const QMetaObjectPrivate *priv(const uint* data) class QMetaMethodBuilderPrivate { public: - QMetaMethodBuilderPrivate() {} // for QVector, don't use QMetaMethodBuilderPrivate (QMetaMethod::MethodType _methodType, const QByteArray& _signature, @@ -145,7 +145,6 @@ Q_DECLARE_TYPEINFO(QMetaMethodBuilderPrivate, Q_MOVABLE_TYPE); class QMetaPropertyBuilderPrivate { public: - QMetaPropertyBuilderPrivate() {} // for QVector, don't use QMetaPropertyBuilderPrivate (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1, int _revision = 0) @@ -184,7 +183,6 @@ Q_DECLARE_TYPEINFO(QMetaPropertyBuilderPrivate, Q_MOVABLE_TYPE); class QMetaEnumBuilderPrivate { public: - QMetaEnumBuilderPrivate() {} // for QVector, don't use QMetaEnumBuilderPrivate(const QByteArray& _name) : name(_name), isFlag(false) { @@ -213,20 +211,20 @@ public: QByteArray className; const QMetaObject *superClass; QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction; - QVector<QMetaMethodBuilderPrivate> methods; - QVector<QMetaMethodBuilderPrivate> constructors; - QVector<QMetaPropertyBuilderPrivate> properties; + std::vector<QMetaMethodBuilderPrivate> methods; + std::vector<QMetaMethodBuilderPrivate> constructors; + std::vector<QMetaPropertyBuilderPrivate> properties; QList<QByteArray> classInfoNames; QList<QByteArray> classInfoValues; - QVector<QMetaEnumBuilderPrivate> enumerators; + std::vector<QMetaEnumBuilderPrivate> enumerators; QList<const QMetaObject *> relatedMetaObjects; int flags; }; bool QMetaObjectBuilderPrivate::hasRevisionedProperties() const { - for (int i = 0; i < properties.size(); ++i) { - if (properties.at(i).revision) + for (const auto &property : properties) { + if (property.revision) return true; } return false; @@ -234,8 +232,8 @@ bool QMetaObjectBuilderPrivate::hasRevisionedProperties() const bool QMetaObjectBuilderPrivate::hasRevisionedMethods() const { - for (int i = 0; i < methods.size(); ++i) { - if (methods.at(i).revision) + for (const auto &method : methods) { + if (method.revision) return true; } return false; @@ -353,7 +351,7 @@ void QMetaObjectBuilder::setFlags(MetaObjectFlags flags) */ int QMetaObjectBuilder::methodCount() const { - return d->methods.size(); + return int(d->methods.size()); } /*! @@ -363,7 +361,7 @@ int QMetaObjectBuilder::methodCount() const */ int QMetaObjectBuilder::constructorCount() const { - return d->constructors.size(); + return int(d->constructors.size()); } /*! @@ -374,7 +372,7 @@ int QMetaObjectBuilder::constructorCount() const */ int QMetaObjectBuilder::propertyCount() const { - return d->properties.size(); + return int(d->properties.size()); } /*! @@ -386,7 +384,7 @@ int QMetaObjectBuilder::propertyCount() const */ int QMetaObjectBuilder::enumeratorCount() const { - return d->enumerators.size(); + return int(d->enumerators.size()); } /*! @@ -427,8 +425,8 @@ int QMetaObjectBuilder::relatedMetaObjectCount() const */ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature) { - int index = d->methods.size(); - d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature)); + int index = int(d->methods.size()); + d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature)); return QMetaMethodBuilder(this, index); } @@ -444,8 +442,8 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature) QMetaMethodBuilder QMetaObjectBuilder::addMethod (const QByteArray& signature, const QByteArray& returnType) { - int index = d->methods.size(); - d->methods.append(QMetaMethodBuilderPrivate + int index = int(d->methods.size()); + d->methods.push_back(QMetaMethodBuilderPrivate (QMetaMethod::Method, signature, returnType)); return QMetaMethodBuilder(this, index); } @@ -491,8 +489,8 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype) */ QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature) { - int index = d->methods.size(); - d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature)); + int index = int(d->methods.size()); + d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature)); return QMetaMethodBuilder(this, index); } @@ -506,8 +504,8 @@ QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature) */ QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature) { - int index = d->methods.size(); - d->methods.append(QMetaMethodBuilderPrivate + int index = int(d->methods.size()); + d->methods.push_back(QMetaMethodBuilderPrivate (QMetaMethod::Signal, signature, QByteArray("void"), QMetaMethod::Public)); return QMetaMethodBuilder(this, index); } @@ -523,9 +521,9 @@ QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature) */ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature) { - int index = d->constructors.size(); - d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature, - /*returnType=*/QByteArray())); + int index = int(d->constructors.size()); + d->constructors.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature, + /*returnType=*/QByteArray())); return QMetaMethodBuilder(this, -(index + 1)); } @@ -564,8 +562,8 @@ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototy QMetaPropertyBuilder QMetaObjectBuilder::addProperty (const QByteArray& name, const QByteArray& type, int notifierId) { - int index = d->properties.size(); - d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId)); + int index = int(d->properties.size()); + d->properties.push_back(QMetaPropertyBuilderPrivate(name, type, notifierId)); return QMetaPropertyBuilder(this, index); } @@ -615,8 +613,8 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot */ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name) { - int index = d->enumerators.size(); - d->enumerators.append(QMetaEnumBuilderPrivate(name)); + int index = int(d->enumerators.size()); + d->enumerators.push_back(QMetaEnumBuilderPrivate(name)); return QMetaEnumBuilder(this, index); } @@ -762,7 +760,7 @@ void QMetaObjectBuilder::addMetaObject */ QMetaMethodBuilder QMetaObjectBuilder::method(int index) const { - if (index >= 0 && index < d->methods.size()) + if (uint(index) < d->methods.size()) return QMetaMethodBuilder(this, index); else return QMetaMethodBuilder(); @@ -775,7 +773,7 @@ QMetaMethodBuilder QMetaObjectBuilder::method(int index) const */ QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const { - if (index >= 0 && index < d->constructors.size()) + if (uint(index) < d->constructors.size()) return QMetaMethodBuilder(this, -(index + 1)); else return QMetaMethodBuilder(); @@ -788,7 +786,7 @@ QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const */ QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const { - if (index >= 0 && index < d->properties.size()) + if (uint(index) < d->properties.size()) return QMetaPropertyBuilder(this, index); else return QMetaPropertyBuilder(); @@ -802,7 +800,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const */ QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const { - if (index >= 0 && index < d->enumerators.size()) + if (uint(index) < d->enumerators.size()) return QMetaEnumBuilder(this, index); else return QMetaEnumBuilder(); @@ -866,15 +864,15 @@ QByteArray QMetaObjectBuilder::classInfoValue(int index) const */ void QMetaObjectBuilder::removeMethod(int index) { - if (index >= 0 && index < d->methods.size()) { - d->methods.removeAt(index); - for (int prop = 0; prop < d->properties.size(); ++prop) { + if (uint(index) < d->methods.size()) { + d->methods.erase(d->methods.begin() + index); + for (auto &property : d->properties) { // Adjust the indices of property notify signal references. - if (d->properties[prop].notifySignal == index) { - d->properties[prop].notifySignal = -1; - d->properties[prop].setFlag(Notify, false); - } else if (d->properties[prop].notifySignal > index) - (d->properties[prop].notifySignal)--; + if (property.notifySignal == index) { + property.notifySignal = -1; + property.setFlag(Notify, false); + } else if (property.notifySignal > index) + property.notifySignal--; } } } @@ -888,8 +886,8 @@ void QMetaObjectBuilder::removeMethod(int index) */ void QMetaObjectBuilder::removeConstructor(int index) { - if (index >= 0 && index < d->constructors.size()) - d->constructors.removeAt(index); + if (uint(index) < d->constructors.size()) + d->constructors.erase(d->constructors.begin() + index); } /*! @@ -900,8 +898,8 @@ void QMetaObjectBuilder::removeConstructor(int index) */ void QMetaObjectBuilder::removeProperty(int index) { - if (index >= 0 && index < d->properties.size()) - d->properties.removeAt(index); + if (uint(index) < d->properties.size()) + d->properties.erase(d->properties.begin() + index); } /*! @@ -913,8 +911,8 @@ void QMetaObjectBuilder::removeProperty(int index) */ void QMetaObjectBuilder::removeEnumerator(int index) { - if (index >= 0 && index < d->enumerators.size()) - d->enumerators.removeAt(index); + if (uint(index) < d->enumerators.size()) + d->enumerators.erase(d->enumerators.begin() + index); } /*! @@ -959,9 +957,9 @@ void QMetaObjectBuilder::removeRelatedMetaObject(int index) int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature) { QByteArray sig = QMetaObject::normalizedSignature(signature); - for (int index = 0; index < d->methods.size(); ++index) { - if (sig == d->methods[index].signature) - return index; + for (const auto &method : d->methods) { + if (sig == method.signature) + return int(&method - &d->methods.front()); } return -1; } @@ -975,10 +973,9 @@ int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature) int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature) { QByteArray sig = QMetaObject::normalizedSignature(signature); - for (int index = 0; index < d->methods.size(); ++index) { - if (sig == d->methods[index].signature && - d->methods[index].methodType() == QMetaMethod::Signal) - return index; + for (const auto &method : d->methods) { + if (method.methodType() == QMetaMethod::Signal && sig == method.signature) + return int(&method - &d->methods.front()); } return -1; } @@ -992,10 +989,9 @@ int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature) int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature) { QByteArray sig = QMetaObject::normalizedSignature(signature); - for (int index = 0; index < d->methods.size(); ++index) { - if (sig == d->methods[index].signature && - d->methods[index].methodType() == QMetaMethod::Slot) - return index; + for (const auto &method : d->methods) { + if (method.methodType() == QMetaMethod::Slot && sig == method.signature) + return int(&method - &d->methods.front()); } return -1; } @@ -1009,9 +1005,9 @@ int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature) int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature) { QByteArray sig = QMetaObject::normalizedSignature(signature); - for (int index = 0; index < d->constructors.size(); ++index) { - if (sig == d->constructors[index].signature) - return index; + for (const auto &constructor : d->constructors) { + if (sig == constructor.signature) + return int(&constructor - &d->constructors.front()); } return -1; } @@ -1024,9 +1020,9 @@ int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature) */ int QMetaObjectBuilder::indexOfProperty(const QByteArray& name) { - for (int index = 0; index < d->properties.size(); ++index) { - if (name == d->properties[index].name) - return index; + for (const auto &property : d->properties) { + if (name == property.name) + return int(&property - &d->properties.front()); } return -1; } @@ -1039,9 +1035,9 @@ int QMetaObjectBuilder::indexOfProperty(const QByteArray& name) */ int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name) { - for (int index = 0; index < d->enumerators.size(); ++index) { - if (name == d->enumerators[index].name) - return index; + for (const auto &enumerator : d->enumerators) { + if (name == enumerator.name) + return int(&enumerator - &d->enumerators.front()); } return -1; } @@ -1155,11 +1151,11 @@ void QMetaStringTable::writeBlob(char *out) const // Returns the sum of all parameters (including return type) for the given // \a methods. This is needed for calculating the size of the methods' // parameter type/name meta-data. -static int aggregateParameterCount(const QVector<QMetaMethodBuilderPrivate> &methods) +static int aggregateParameterCount(const std::vector<QMetaMethodBuilderPrivate> &methods) { int sum = 0; - for (int i = 0; i < methods.size(); ++i) - sum += methods.at(i).parameterCount() + 1; // +1 for return type + for (const auto &method : methods) + sum += method.parameterCount() + 1; // +1 for return type return sum; } @@ -1200,8 +1196,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, = reinterpret_cast<QMetaObjectPrivate *>(buf + size); int pmetaSize = size; dataIndex = MetaObjectPrivateFieldCount; - for (index = 0; index < d->properties.size(); ++index) { - if (d->properties[index].notifySignal != -1) { + for (const auto &property : d->properties) { + if (property.notifySignal != -1) { hasNotifySignals = true; break; } @@ -1209,8 +1205,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, int methodParametersDataSize = ((aggregateParameterCount(d->methods) + aggregateParameterCount(d->constructors)) * 2) // types and parameter names - - d->methods.size() // return "parameters" don't have names - - d->constructors.size(); // "this" parameters don't have names + - int(d->methods.size()) // return "parameters" don't have names + - int(d->constructors.size()); // "this" parameters don't have names if (buf) { Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc"); pmeta->revision = QMetaObjectPrivate::OutputRevision; @@ -1222,51 +1218,49 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, pmeta->classInfoData = dataIndex; dataIndex += 2 * d->classInfoNames.size(); - pmeta->methodCount = d->methods.size(); + pmeta->methodCount = int(d->methods.size()); pmeta->methodData = dataIndex; - dataIndex += 5 * d->methods.size(); + dataIndex += 5 * int(d->methods.size()); if (hasRevisionedMethods) - dataIndex += d->methods.size(); + dataIndex += int(d->methods.size()); paramsIndex = dataIndex; dataIndex += methodParametersDataSize; - pmeta->propertyCount = d->properties.size(); + pmeta->propertyCount = int(d->properties.size()); pmeta->propertyData = dataIndex; - dataIndex += 3 * d->properties.size(); + dataIndex += 3 * int(d->properties.size()); if (hasNotifySignals) - dataIndex += d->properties.size(); + dataIndex += int(d->properties.size()); if (hasRevisionedProperties) - dataIndex += d->properties.size(); + dataIndex += int(d->properties.size()); - pmeta->enumeratorCount = d->enumerators.size(); + pmeta->enumeratorCount = int(d->enumerators.size()); pmeta->enumeratorData = dataIndex; - dataIndex += 4 * d->enumerators.size(); + dataIndex += 4 * int(d->enumerators.size()); - pmeta->constructorCount = d->constructors.size(); + pmeta->constructorCount = int(d->constructors.size()); pmeta->constructorData = dataIndex; - dataIndex += 5 * d->constructors.size(); + dataIndex += 5 * int(d->constructors.size()); } else { - dataIndex += 2 * d->classInfoNames.size(); - dataIndex += 5 * d->methods.size(); + dataIndex += 2 * int(d->classInfoNames.size()); + dataIndex += 5 * int(d->methods.size()); if (hasRevisionedMethods) - dataIndex += d->methods.size(); + dataIndex += int(d->methods.size()); paramsIndex = dataIndex; dataIndex += methodParametersDataSize; - dataIndex += 3 * d->properties.size(); + dataIndex += 3 * int(d->properties.size()); if (hasNotifySignals) - dataIndex += d->properties.size(); + dataIndex += int(d->properties.size()); if (hasRevisionedProperties) - dataIndex += d->properties.size(); - dataIndex += 4 * d->enumerators.size(); - dataIndex += 5 * d->constructors.size(); + dataIndex += int(d->properties.size()); + dataIndex += 4 * int(d->enumerators.size()); + dataIndex += 5 * int(d->constructors.size()); } // Allocate space for the enumerator key names and values. enumIndex = dataIndex; - for (index = 0; index < d->enumerators.size(); ++index) { - QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]); - dataIndex += 2 * enumerator->keys.size(); - } + for (const auto &enumerator : d->enumerators) + dataIndex += 2 * enumerator.keys.size(); // Zero terminator at the end of the data offset table. ++dataIndex; @@ -1305,44 +1299,41 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, // Output the methods in the class. Q_ASSERT(!buf || dataIndex == pmeta->methodData); - for (index = 0; index < d->methods.size(); ++index) { - QMetaMethodBuilderPrivate *method = &(d->methods[index]); - int name = strings.enter(method->name()); - int argc = method->parameterCount(); - int tag = strings.enter(method->tag); - int attrs = method->attributes; + for (const auto &method : d->methods) { + int name = strings.enter(method.name()); + int argc = method.parameterCount(); + int tag = strings.enter(method.tag); + int attrs = method.attributes; if (buf) { data[dataIndex] = name; data[dataIndex + 1] = argc; data[dataIndex + 2] = paramsIndex; data[dataIndex + 3] = tag; data[dataIndex + 4] = attrs; - if (method->methodType() == QMetaMethod::Signal) + if (method.methodType() == QMetaMethod::Signal) pmeta->signalCount++; } dataIndex += 5; paramsIndex += 1 + argc * 2; } if (hasRevisionedMethods) { - for (index = 0; index < d->methods.size(); ++index) { - QMetaMethodBuilderPrivate *method = &(d->methods[index]); + for (const auto &method : d->methods) { if (buf) - data[dataIndex] = method->revision; + data[dataIndex] = method.revision; ++dataIndex; } } // Output the method parameters in the class. - Q_ASSERT(!buf || dataIndex == pmeta->methodData + d->methods.size() * 5 - + (hasRevisionedMethods ? d->methods.size() : 0)); + Q_ASSERT(!buf || dataIndex == pmeta->methodData + int(d->methods.size()) * 5 + + (hasRevisionedMethods ? int(d->methods.size()) : 0)); for (int x = 0; x < 2; ++x) { - QVector<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors; - for (index = 0; index < methods.size(); ++index) { - QMetaMethodBuilderPrivate *method = &(methods[index]); - QList<QByteArray> paramTypeNames = method->parameterTypes(); + const std::vector<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors; + for (const auto &method : methods) { + const QList<QByteArray> paramTypeNames = method.parameterTypes(); int paramCount = paramTypeNames.size(); for (int i = -1; i < paramCount; ++i) { - const QByteArray &typeName = (i < 0) ? method->returnType : paramTypeNames.at(i); + const QByteArray &typeName = (i < 0) ? method.returnType : paramTypeNames.at(i); int typeInfo; if (QtPrivate::isBuiltinType(typeName)) typeInfo = QMetaType::type(typeName); @@ -1353,7 +1344,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, ++dataIndex; } - QList<QByteArray> paramNames = method->parameterNames; + QList<QByteArray> paramNames = method.parameterNames; while (paramNames.size() < paramCount) paramNames.append(QByteArray()); for (int i = 0; i < paramCount; ++i) { @@ -1367,19 +1358,18 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, // Output the properties in the class. Q_ASSERT(!buf || dataIndex == pmeta->propertyData); - for (index = 0; index < d->properties.size(); ++index) { - QMetaPropertyBuilderPrivate *prop = &(d->properties[index]); - int name = strings.enter(prop->name); + for (const auto &prop : d->properties) { + int name = strings.enter(prop.name); int typeInfo; - if (QtPrivate::isBuiltinType(prop->type)) - typeInfo = QMetaType::type(prop->type); + if (QtPrivate::isBuiltinType(prop.type)) + typeInfo = QMetaType::type(prop.type); else - typeInfo = IsUnresolvedType | strings.enter(prop->type); + typeInfo = IsUnresolvedType | strings.enter(prop.type); - int flags = prop->flags; + int flags = prop.flags; - if (!QtPrivate::isBuiltinType(prop->type)) + if (!QtPrivate::isBuiltinType(prop.type)) flags |= EnumOrFlag; if (buf) { @@ -1390,11 +1380,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, dataIndex += 3; } if (hasNotifySignals) { - for (index = 0; index < d->properties.size(); ++index) { - QMetaPropertyBuilderPrivate *prop = &(d->properties[index]); + for (const auto &prop : d->properties) { if (buf) { - if (prop->notifySignal != -1) - data[dataIndex] = prop->notifySignal; + if (prop.notifySignal != -1) + data[dataIndex] = prop.notifySignal; else data[dataIndex] = 0; } @@ -1402,21 +1391,19 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, } } if (hasRevisionedProperties) { - for (index = 0; index < d->properties.size(); ++index) { - QMetaPropertyBuilderPrivate *prop = &(d->properties[index]); + for (const auto &prop : d->properties) { if (buf) - data[dataIndex] = prop->revision; + data[dataIndex] = prop.revision; ++dataIndex; } } // Output the enumerators in the class. Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData); - for (index = 0; index < d->enumerators.size(); ++index) { - QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]); - int name = strings.enter(enumerator->name); - int isFlag = (int)(enumerator->isFlag); - int count = enumerator->keys.size(); + for (const auto &enumerator : d->enumerators) { + int name = strings.enter(enumerator.name); + int isFlag = (int)(enumerator.isFlag); + int count = enumerator.keys.size(); int enumOffset = enumIndex; if (buf) { data[dataIndex] = name; @@ -1425,10 +1412,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, data[dataIndex + 3] = enumOffset; } for (int key = 0; key < count; ++key) { - int keyIndex = strings.enter(enumerator->keys[key]); + int keyIndex = strings.enter(enumerator.keys[key]); if (buf) { data[enumOffset++] = keyIndex; - data[enumOffset++] = enumerator->values[key]; + data[enumOffset++] = enumerator.values[key]; } } dataIndex += 4; @@ -1437,12 +1424,11 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, // Output the constructors in the class. Q_ASSERT(!buf || dataIndex == pmeta->constructorData); - for (index = 0; index < d->constructors.size(); ++index) { - QMetaMethodBuilderPrivate *method = &(d->constructors[index]); - int name = strings.enter(method->name()); - int argc = method->parameterCount(); - int tag = strings.enter(method->tag); - int attrs = method->attributes; + for (const auto &ctor : d->constructors) { + int name = strings.enter(ctor.name()); + int argc = ctor.parameterCount(); + int tag = strings.enter(ctor.tag); + int attrs = ctor.attributes; if (buf) { data[dataIndex] = name; data[dataIndex + 1] = argc; @@ -1612,10 +1598,10 @@ void QMetaObjectBuilder::serialize(QDataStream& stream) const // Write the counts for each type of class member. stream << d->classInfoNames.size(); - stream << d->methods.size(); - stream << d->properties.size(); - stream << d->enumerators.size(); - stream << d->constructors.size(); + stream << int(d->methods.size()); + stream << int(d->properties.size()); + stream << int(d->enumerators.size()); + stream << int(d->constructors.size()); stream << d->relatedMetaObjects.size(); // Write the items of class information. @@ -1625,45 +1611,41 @@ void QMetaObjectBuilder::serialize(QDataStream& stream) const } // Write the methods. - for (index = 0; index < d->methods.size(); ++index) { - const QMetaMethodBuilderPrivate *method = &(d->methods[index]); - stream << method->signature; - stream << method->returnType; - stream << method->parameterNames; - stream << method->tag; - stream << method->attributes; - if (method->revision) - stream << method->revision; + for (const auto &method : d->methods) { + stream << method.signature; + stream << method.returnType; + stream << method.parameterNames; + stream << method.tag; + stream << method.attributes; + if (method.revision) + stream << method.revision; } // Write the properties. - for (index = 0; index < d->properties.size(); ++index) { - const QMetaPropertyBuilderPrivate *property = &(d->properties[index]); - stream << property->name; - stream << property->type; - stream << property->flags; - stream << property->notifySignal; - if (property->revision) - stream << property->revision; + for (const auto &property : d->properties) { + stream << property.name; + stream << property.type; + stream << property.flags; + stream << property.notifySignal; + if (property.revision) + stream << property.revision; } // Write the enumerators. - for (index = 0; index < d->enumerators.size(); ++index) { - const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]); - stream << enumerator->name; - stream << enumerator->isFlag; - stream << enumerator->keys; - stream << enumerator->values; + for (const auto &enumerator : d->enumerators) { + stream << enumerator.name; + stream << enumerator.isFlag; + stream << enumerator.keys; + stream << enumerator.values; } // Write the constructors. - for (index = 0; index < d->constructors.size(); ++index) { - const QMetaMethodBuilderPrivate *method = &(d->constructors[index]); - stream << method->signature; - stream << method->returnType; - stream << method->parameterNames; - stream << method->tag; - stream << method->attributes; + for (const auto &ctor : d->constructors) { + stream << ctor.signature; + stream << ctor.returnType; + stream << ctor.parameterNames; + stream << ctor.tag; + stream << ctor.attributes; } // Write the related meta objects. @@ -1770,14 +1752,14 @@ void QMetaObjectBuilder::deserialize return; stream >> name; addMethod(name); - QMetaMethodBuilderPrivate *method = &(d->methods[index]); - stream >> method->returnType; - stream >> method->parameterNames; - stream >> method->tag; - stream >> method->attributes; - if (method->attributes & MethodRevisioned) - stream >> method->revision; - if (method->methodType() == QMetaMethod::Constructor) { + QMetaMethodBuilderPrivate &method = d->methods[index]; + stream >> method.returnType; + stream >> method.parameterNames; + stream >> method.tag; + stream >> method.attributes; + if (method.attributes & MethodRevisioned) + stream >> method.revision; + if (method.methodType() == QMetaMethod::Constructor) { // Cannot add a constructor in this set of methods. stream.setStatus(QDataStream::ReadCorruptData); return; @@ -1792,23 +1774,23 @@ void QMetaObjectBuilder::deserialize stream >> name; stream >> type; addProperty(name, type); - QMetaPropertyBuilderPrivate *property = &(d->properties[index]); - stream >> property->flags; - stream >> property->notifySignal; - if (property->notifySignal < -1 || - property->notifySignal >= d->methods.size()) { + QMetaPropertyBuilderPrivate &property = d->properties[index]; + stream >> property.flags; + stream >> property.notifySignal; + if (property.notifySignal < -1 || + property.notifySignal >= int(d->methods.size())) { // Notify signal method index is out of range. stream.setStatus(QDataStream::ReadCorruptData); return; } - if (property->notifySignal >= 0 && - d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) { + if (property.notifySignal >= 0 && + d->methods[property.notifySignal].methodType() != QMetaMethod::Signal) { // Notify signal method index does not refer to a signal. stream.setStatus(QDataStream::ReadCorruptData); return; } - if (property->flags & Revisioned) - stream >> property->revision; + if (property.flags & Revisioned) + stream >> property.revision; } // Read the enumerators. @@ -1817,11 +1799,11 @@ void QMetaObjectBuilder::deserialize return; stream >> name; addEnumerator(name); - QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]); - stream >> enumerator->isFlag; - stream >> enumerator->keys; - stream >> enumerator->values; - if (enumerator->keys.size() != enumerator->values.size()) { + QMetaEnumBuilderPrivate &enumerator = d->enumerators[index]; + stream >> enumerator.isFlag; + stream >> enumerator.keys; + stream >> enumerator.values; + if (enumerator.keys.size() != enumerator.values.size()) { // Mismatch between number of keys and number of values. stream.setStatus(QDataStream::ReadCorruptData); return; @@ -1834,12 +1816,12 @@ void QMetaObjectBuilder::deserialize return; stream >> name; addConstructor(name); - QMetaMethodBuilderPrivate *method = &(d->constructors[index]); - stream >> method->returnType; - stream >> method->parameterNames; - stream >> method->tag; - stream >> method->attributes; - if (method->methodType() != QMetaMethod::Constructor) { + QMetaMethodBuilderPrivate &method = d->constructors[index]; + stream >> method.returnType; + stream >> method.parameterNames; + stream >> method.tag; + stream >> method.attributes; + if (method.methodType() != QMetaMethod::Constructor) { // The type must be Constructor. stream.setStatus(QDataStream::ReadCorruptData); return; @@ -1875,9 +1857,9 @@ void QMetaObjectBuilder::deserialize QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const { // Positive indices indicate methods, negative indices indicate constructors. - if (_mobj && _index >= 0 && _index < _mobj->d->methods.size()) + if (_mobj && _index >= 0 && _index < int(_mobj->d->methods.size())) return &(_mobj->d->methods[_index]); - else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size()) + else if (_mobj && -_index >= 1 && -_index <= int(_mobj->d->constructors.size())) return &(_mobj->d->constructors[(-_index) - 1]); else return 0; @@ -2116,7 +2098,7 @@ void QMetaMethodBuilder::setRevision(int revision) QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const { - if (_mobj && _index >= 0 && _index < _mobj->d->properties.size()) + if (_mobj && _index >= 0 && _index < int(_mobj->d->properties.size())) return &(_mobj->d->properties[_index]); else return 0; @@ -2588,7 +2570,7 @@ void QMetaPropertyBuilder::setRevision(int revision) QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const { - if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size()) + if (_mobj && _index >= 0 && _index < int(_mobj->d->enumerators.size())) return &(_mobj->d->enumerators[_index]); else return 0; diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index e6d745bb74..c0caa3cca5 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -1074,7 +1074,7 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, previousFlags = QMetaType::typeFlags(idx); } - if (previousSize != size) { + if (Q_UNLIKELY(previousSize != size)) { qFatal("QMetaType::registerType: Binary compatibility break " "-- Size mismatch for type '%s' [%i]. Previously registered " "size %i, now registering size %i.", @@ -1084,7 +1084,7 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, // these flags cannot change in a binary compatible way: const int binaryCompatibilityFlag = PointerToQObject | IsEnumeration | SharedPointerToQObject | WeakPointerToQObject | TrackingPointerToQObject; - if ((previousFlags ^ flags) & binaryCompatibilityFlag) { + if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) { const char *msg = "QMetaType::registerType: Binary compatibility break. " "\nType flags for type '%s' [%i] don't match. Previously " diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c316ebc69f..a4531e29eb 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -203,7 +203,7 @@ QObjectPrivate::QObjectPrivate(int version) // This allows incompatible versions to be loaded, possibly for testing. Q_UNUSED(version); #else - if (version != QObjectPrivateVersion) + if (Q_UNLIKELY(version != QObjectPrivateVersion)) qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)", version, QObjectPrivateVersion); #endif diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 64c5b58fd4..118316484b 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -293,7 +293,7 @@ public: connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { -#if defined (Q_COMPILER_DECLTYPE) && defined (Q_COMPILER_VARIADIC_TEMPLATES) +#if defined (Q_COMPILER_VARIADIC_TEMPLATES) typedef QtPrivate::FunctionPointer<Func1> SignalType; const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value; @@ -313,15 +313,7 @@ public: Functors with overloaded or templated operator() are only supported if the compiler supports C++11 variadic templates */ -#ifndef Q_COMPILER_DECLTYPE //Workaround the lack of decltype using another function as indirection - return connect_functor(sender, signal, context, slot, &Func2::operator(), type); } - template <typename Func1, typename Func2, typename Func2Operator> - static inline QMetaObject::Connection connect_functor(const QObject *sender, Func1 signal, const QObject *context, - Func2 slot, Func2Operator, Qt::ConnectionType type) { - typedef QtPrivate::FunctionPointer<Func2Operator> SlotType ; -#else typedef QtPrivate::FunctionPointer<decltype(&Func2::operator())> SlotType ; -#endif typedef QtPrivate::FunctionPointer<Func1> SignalType; typedef typename SlotType::ReturnType SlotReturnType; const int SlotArgumentCount = SlotType::ArgumentCount; diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index d5574a4dd1..dc445a426d 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -593,7 +593,7 @@ namespace QtPrivate { }; #endif -#if defined(Q_COMPILER_DECLTYPE) && defined(Q_COMPILER_VARIADIC_TEMPLATES) +#if defined(Q_COMPILER_VARIADIC_TEMPLATES) /* Find the maximum number of arguments a functor object can take and be still compatible with the arguments from the signal. diff --git a/src/corelib/kernel/qpoll.cpp b/src/corelib/kernel/qpoll.cpp new file mode 100644 index 0000000000..b152518c00 --- /dev/null +++ b/src/corelib/kernel/qpoll.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcore_unix_p.h" + +QT_BEGIN_NAMESPACE + +#define QT_POLL_READ_MASK (POLLIN | POLLRDNORM) +#define QT_POLL_WRITE_MASK (POLLOUT | POLLWRNORM | POLLWRBAND) +#define QT_POLL_EXCEPT_MASK (POLLPRI | POLLRDBAND) +#define QT_POLL_ERROR_MASK (POLLERR | POLLNVAL) +#define QT_POLL_EVENTS_MASK (QT_POLL_READ_MASK | QT_POLL_WRITE_MASK | QT_POLL_EXCEPT_MASK) + +static inline int qt_poll_prepare(struct pollfd *fds, nfds_t nfds, + fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) +{ + int max_fd = -1; + + FD_ZERO(read_fds); + FD_ZERO(write_fds); + FD_ZERO(except_fds); + + for (nfds_t i = 0; i < nfds; i++) { + if (fds[i].fd >= FD_SETSIZE) { + errno = EINVAL; + return -1; + } + + if ((fds[i].fd < 0) || (fds[i].revents & QT_POLL_ERROR_MASK)) + continue; + + if (fds[i].events & QT_POLL_READ_MASK) + FD_SET(fds[i].fd, read_fds); + + if (fds[i].events & QT_POLL_WRITE_MASK) + FD_SET(fds[i].fd, write_fds); + + if (fds[i].events & QT_POLL_EXCEPT_MASK) + FD_SET(fds[i].fd, except_fds); + + if (fds[i].events & QT_POLL_EVENTS_MASK) + max_fd = qMax(max_fd, fds[i].fd); + } + + return max_fd + 1; +} + +static inline void qt_poll_examine_ready_read(struct pollfd &pfd) +{ + int res; + char data; + + EINTR_LOOP(res, ::recv(pfd.fd, &data, sizeof(data), MSG_PEEK)); + const int error = (res < 0) ? errno : 0; + + if (res == 0) { + pfd.revents |= POLLHUP; + } else if (res > 0 || error == ENOTSOCK || error == ENOTCONN) { + pfd.revents |= QT_POLL_READ_MASK & pfd.events; + } else { + switch (error) { + case ESHUTDOWN: + case ECONNRESET: + case ECONNABORTED: + case ENETRESET: + pfd.revents |= POLLHUP; + break; + default: + pfd.revents |= POLLERR; + break; + } + } +} + +static inline int qt_poll_sweep(struct pollfd *fds, nfds_t nfds, + fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) +{ + int result = 0; + + for (nfds_t i = 0; i < nfds; i++) { + if (fds[i].fd < 0) + continue; + + if (FD_ISSET(fds[i].fd, read_fds)) + qt_poll_examine_ready_read(fds[i]); + + if (FD_ISSET(fds[i].fd, write_fds)) + fds[i].revents |= QT_POLL_WRITE_MASK & fds[i].events; + + if (FD_ISSET(fds[i].fd, except_fds)) + fds[i].revents |= QT_POLL_EXCEPT_MASK & fds[i].events; + + if (fds[i].revents != 0) + result++; + } + + return result; +} + +static inline bool qt_poll_is_bad_fd(int fd) +{ + int ret; + EINTR_LOOP(ret, fcntl(fd, F_GETFD)); + return (ret == -1 && errno == EBADF); +} + +static inline int qt_poll_mark_bad_fds(struct pollfd *fds, const nfds_t nfds) +{ + int n_marked = 0; + + for (nfds_t i = 0; i < nfds; i++) { + if (fds[i].fd < 0) + continue; + + if (fds[i].revents & QT_POLL_ERROR_MASK) + continue; + + if (qt_poll_is_bad_fd(fds[i].fd)) { + fds[i].revents |= POLLNVAL; + n_marked++; + } + } + + return n_marked; +} + +int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts) +{ + if (!fds && nfds) { + errno = EFAULT; + return -1; + } + + fd_set read_fds, write_fds, except_fds; + struct timeval tv, *ptv = 0; + + if (timeout_ts) { + tv = timespecToTimeval(*timeout_ts); + ptv = &tv; + } + + int n_bad_fds = 0; + + for (nfds_t i = 0; i < nfds; i++) { + fds[i].revents = 0; + + if (fds[i].fd < 0) + continue; + + if (fds[i].events & QT_POLL_EVENTS_MASK) + continue; + + if (qt_poll_is_bad_fd(fds[i].fd)) { + // Mark bad file descriptors that have no event flags set + // here, as we won't be passing them to select below and therefore + // need to do the check ourselves + fds[i].revents = POLLNVAL; + n_bad_fds++; + } + } + + forever { + const int max_fd = qt_poll_prepare(fds, nfds, &read_fds, &write_fds, &except_fds); + + if (max_fd < 0) + return max_fd; + + if (n_bad_fds > 0) { + tv.tv_sec = 0; + tv.tv_usec = 0; + ptv = &tv; + } + + const int ret = ::select(max_fd, &read_fds, &write_fds, &except_fds, ptv); + + if (ret == 0) + return n_bad_fds; + + if (ret > 0) + return qt_poll_sweep(fds, nfds, &read_fds, &write_fds, &except_fds); + + if (errno != EBADF) + return -1; + + // We have at least one bad file descriptor that we waited on, find out which and try again + n_bad_fds += qt_poll_mark_bad_fds(fds, nfds); + } +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_blackberry_p.h b/src/corelib/kernel/qpoll_p.h index 7912ae83c5..497058ad6b 100644 --- a/src/corelib/kernel/qeventdispatcher_blackberry_p.h +++ b/src/corelib/kernel/qpoll_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. +** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -31,67 +31,49 @@ ** ****************************************************************************/ -#ifndef QEVENTDISPATCHER_BLACKBERRY_P_H -#define QEVENTDISPATCHER_BLACKBERRY_P_H +#ifndef QPOLL_P_H +#define QPOLL_P_H // // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to +// This file is not part of the Qt API. It exists for the convenience +// of Qt code on Unix. This header file may change from version to // version without notice, or even be removed. // // We mean it. // -#include "private/qeventdispatcher_unix_p.h" +#include <QtCore/qglobal.h> QT_BEGIN_NAMESPACE -class QEventDispatcherBlackberryPrivate; +#ifdef QT_NO_NATIVE_POLL -class Q_CORE_EXPORT QEventDispatcherBlackberry : public QEventDispatcherUNIX -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QEventDispatcherBlackberry) +#include <unistd.h> +#include <time.h> -public: - explicit QEventDispatcherBlackberry(QObject *parent = 0); - ~QEventDispatcherBlackberry(); - - void registerSocketNotifier(QSocketNotifier *notifier); - void unregisterSocketNotifier(QSocketNotifier *notifier); - - void wakeUp(); - -protected: - QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent = 0); - - int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - timespec *timeout); - int ioEvents(int fd); +struct pollfd { + int fd; + short events, revents; }; -struct bpsIOHandlerData; +typedef unsigned long int nfds_t; -class Q_CORE_EXPORT QEventDispatcherBlackberryPrivate : public QEventDispatcherUNIXPrivate -{ - Q_DECLARE_PUBLIC(QEventDispatcherBlackberry) +#define POLLIN 0x001 +#define POLLPRI 0x002 +#define POLLOUT 0x004 +#define POLLERR 0x008 +#define POLLHUP 0x010 +#define POLLNVAL 0x020 +#define POLLRDNORM 0x040 +#define POLLRDBAND 0x080 +#define POLLWRNORM 0x100 +#define POLLWRBAND 0x200 -public: - QEventDispatcherBlackberryPrivate(); - ~QEventDispatcherBlackberryPrivate(); - - int initThreadWakeUp(); - int processThreadWakeUp(int nsel); - - int bps_channel; - int holding_channel; - int loop_level; - QScopedPointer<bpsIOHandlerData> ioData; -}; +#endif // QT_NO_NATIVE_POLL QT_END_NAMESPACE -#endif // QEVENTDISPATCHER_BLACKBERRY_P_H +#endif // QPOLL_P_H diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 2bcc0d4f6a..149bc85a15 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -61,7 +61,7 @@ namespace QSharedMemoryPrivate #include "qsystemsemaphore.h" #include "private/qobject_p.h" -#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) +#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) # include <sys/sem.h> #endif diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 794a4aaa0c..dad471c1b0 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -613,6 +613,13 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo return false; } +Q_NEVER_INLINE +static bool is_readable_file(const QString &name) +{ + const QFileInfo fi(name); + return fi.isReadable() && fi.isFile(); +} + static QString find_translation(const QLocale & locale, const QString & filename, const QString & prefix, @@ -625,9 +632,11 @@ static QString find_translation(const QLocale & locale, if (!path.isEmpty() && !path.endsWith(QLatin1Char('/'))) path += QLatin1Char('/'); } + const QString suffixOrDotQM = suffix.isNull() ? QStringLiteral(".qm") : suffix; - QFileInfo fi; QString realname; + realname += path + filename + prefix; // using += in the hope for some reserve capacity + const int realNameBaseSize = realname.size(); QStringList fuzzyLocales; // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration @@ -646,16 +655,15 @@ static QString find_translation(const QLocale & locale, foreach (QString localeName, languages) { localeName.replace(QLatin1Char('-'), QLatin1Char('_')); - realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix); - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + realname += localeName + suffixOrDotQM; + if (is_readable_file(realname)) return realname; - realname = path + filename + prefix + localeName; - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + realname.truncate(realNameBaseSize + localeName.size()); + if (is_readable_file(realname)) return realname; + realname.truncate(realNameBaseSize); fuzzyLocales.append(localeName); } @@ -668,33 +676,36 @@ static QString find_translation(const QLocale & locale, break; localeName.truncate(rightmost); - realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix); - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + realname += localeName + suffixOrDotQM; + if (is_readable_file(realname)) return realname; - realname = path + filename + prefix + localeName; - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + realname.truncate(realNameBaseSize + localeName.size()); + if (is_readable_file(realname)) return realname; + + realname.truncate(realNameBaseSize); } } + const int realNameBaseSizeFallbacks = path.size() + filename.size(); + + // realname == path + filename + prefix; if (!suffix.isNull()) { - realname = path + filename + suffix; - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + realname.replace(realNameBaseSizeFallbacks, prefix.size(), suffix); + // realname == path + filename; + if (is_readable_file(realname)) return realname; + realname.replace(realNameBaseSizeFallbacks, suffix.size(), prefix); } - realname = path + filename + prefix; - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + // realname == path + filename + prefix; + if (is_readable_file(realname)) return realname; - realname = path + filename; - fi.setFile(realname); - if (fi.isReadable() && fi.isFile()) + realname.truncate(realNameBaseSizeFallbacks); + // realname == path + filename; + if (is_readable_file(realname)) return realname; return QString(); diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 3e6aefab2a..1d7128721f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -56,6 +56,7 @@ #include "qbytearraylist.h" #endif #include "private/qvariant_p.h" +#include "private/qlocale_p.h" #include "qmetatype_p.h" #include <qmetaobject.h> @@ -71,18 +72,6 @@ QT_BEGIN_NAMESPACE -#ifndef DBL_MANT_DIG -# define DBL_MANT_DIG 53 -#endif -#ifndef FLT_MANT_DIG -# define FLT_MANT_DIG 24 -#endif - -const int log10_2_10000 = 30103; // log10(2) * 100000 -// same as C++11 std::numeric_limits<T>::max_digits10 -const int max_digits10_double = (DBL_MANT_DIG * log10_2_10000) / 100000 + 2; -const int max_digits10_float = (FLT_MANT_DIG * log10_2_10000) / 100000 + 2; - namespace { class HandlersManager { @@ -433,10 +422,10 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *str = QString::number(qMetaTypeUNumber(d)); break; case QMetaType::Float: - *str = QString::number(d->data.f, 'g', max_digits10_float); + *str = QString::number(d->data.f, 'g', QLocale::FloatingPointShortest); break; case QVariant::Double: - *str = QString::number(d->data.d, 'g', max_digits10_double); + *str = QString::number(d->data.d, 'g', QLocale::FloatingPointShortest); break; #if !defined(QT_NO_DATESTRING) case QVariant::Date: @@ -625,10 +614,10 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *ba = v_cast<QString>(d)->toUtf8(); break; case QVariant::Double: - *ba = QByteArray::number(d->data.d, 'g', max_digits10_double); + *ba = QByteArray::number(d->data.d, 'g', QLocale::FloatingPointShortest); break; case QMetaType::Float: - *ba = QByteArray::number(d->data.f, 'g', max_digits10_float); + *ba = QByteArray::number(d->data.f, 'g', QLocale::FloatingPointShortest); break; case QMetaType::Char: case QMetaType::SChar: diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index bed0e193db..dc3b62bd22 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -568,6 +568,7 @@ inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) return !operator==(v1, v2); } #endif +Q_DECLARE_SHARED(QVariant) class Q_CORE_EXPORT QSequentialIterable { @@ -846,7 +847,6 @@ inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant) #endif #endif -Q_DECLARE_SHARED(QVariant) #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index d84d702982..986eb2c467 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -202,7 +202,6 @@ class QVariantIsNull /// \internal /// This class checks if a type T has method called isNull. Result is kept in the Value property /// TODO Can we somehow generalize it? A macro version? -#if defined(Q_COMPILER_DECLTYPE) // C++11 version template<typename T> class HasIsNullMethod { struct Yes { char unused[1]; }; @@ -214,44 +213,6 @@ class QVariantIsNull public: static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes)); }; -#elif defined(Q_CC_MSVC) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL) // MSVC 2005, 2008 version: no decltype, but 'sealed' classes (>=2010 has decltype) - template<typename T> - class HasIsNullMethod { - struct Yes { char unused[1]; }; - struct No { char unused[2]; }; - Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); - - template<class C> static Yes test(char (*)[(&C::isNull == 0) + 1]); - template<class C> static No test(...); - public: - static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes)); - }; -#else // C++98 version (doesn't work for final classes) - template<typename T, bool IsClass = QTypeInfo<T>::isComplex> - class HasIsNullMethod - { - struct Yes { char unused[1]; }; - struct No { char unused[2]; }; - Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); - - struct FallbackMixin { bool isNull() const; }; - struct Derived : public T, public FallbackMixin {}; // <- doesn't work for final classes - template<class C, C> struct TypeCheck {}; - - template<class C> static Yes test(...); - template<class C> static No test(TypeCheck<bool (FallbackMixin::*)() const, &C::isNull> *); - public: - static const bool Value = (sizeof(test<Derived>(0)) == sizeof(Yes)); - }; - - // We need to exclude primitive types as they won't compile with HasIsNullMethod::Check classes - // anyway it is not a problem as the types do not have isNull method. - template<typename T> - class HasIsNullMethod<T, /* IsClass = */ false> { - public: - static const bool Value = false; - }; -#endif // TODO This part should go to autotests during HasIsNullMethod generalization. Q_STATIC_ASSERT(!HasIsNullMethod<bool>::Value); |