<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "private/qdeclarativedebugserver_p.h"
#include "private/qdeclarativedebugservice_p.h"
#include "private/qdeclarativedebugservice_p_p.h"
#include "private/qdeclarativeengine_p.h"

#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
#include <QtCore/QStringList>

#include <private/qobject_p.h>
#include <private/qguiapplication_p.h>

QT_BEGIN_NAMESPACE

/*
  QDeclarativeDebug Protocol (Version 1):

  handshake:
    1. Client sends
         "QDeclarativeDebugServer" 0 version pluginNames
       version: an int representing the highest protocol version the client knows
       pluginNames: plugins available on client side
    2. Server sends
         "QDeclarativeDebugClient" 0 version pluginNames
       version: an int representing the highest protocol version the client & server know
       pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
  client plugin advertisement
    1. Client sends
         "QDeclarativeDebugServer" 1 pluginNames
  server plugin advertisement
    1. Server sends
         "QDeclarativeDebugClient" 1 pluginNames
  plugin communication:
       Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
  */

const int protocolVersion = 1;

class QDeclarativeDebugServerPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QDeclarativeDebugServer)
public:
    QDeclarativeDebugServerPrivate();

    void advertisePlugins();

    QDeclarativeDebugServerConnection *connection;
    QHash<QString, QDeclarativeDebugService *> plugins;
    QStringList clientPlugins;
    bool gotHello;
    QString waitingForMsgFromService;
    bool waitingForMsgSucceeded;

private:
    // private slot
    void _q_deliverMessage(const QString &serviceName, const QByteArray &message);
    static QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
};

QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() :
    connection(0),
    gotHello(false),
    waitingForMsgSucceeded(false)
{
}

void QDeclarativeDebugServerPrivate::advertisePlugins()
{
    if (!gotHello)
        return;

    QByteArray message;
    {
        QDataStream out(&message, QIODevice::WriteOnly);
        out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys();
    }
    connection->send(message);
}

QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin(
        const QString &pluginName)
{
    QStringList pluginCandidates;
    const QStringList paths = QCoreApplication::libraryPaths();
    foreach (const QString &libPath, paths) {
        const QDir dir(libPath + QLatin1String("/qmltooling"));
        if (dir.exists()) {
            QStringList plugins(dir.entryList(QDir::Files));
            foreach (const QString &pluginPath, plugins) {
                if (QFileInfo(pluginPath).fileName().contains(pluginName))
                    pluginCandidates << dir.absoluteFilePath(pluginPath);
            }
        }
    }

    foreach (const QString &pluginPath, pluginCandidates) {
        QPluginLoader loader(pluginPath);
        if (!loader.load()) {
            continue;
        }
        QDeclarativeDebugServerConnection *connection = 0;
        if (QObject *instance = loader.instance())
            connection = qobject_cast<QDeclarativeDebugServerConnection*>(instance);

        if (connection)
            return connection;
        loader.unload();
    }
    return 0;
}

bool QDeclarativeDebugServer::hasDebuggingClient() const
{
    Q_D(const QDeclarativeDebugServer);
    return d->connection
            && d->connection->isConnected()
            && d->gotHello;
}

QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
{
    static bool commandLineTested = false;
    static QDeclarativeDebugServer *server = 0;

    if (!commandLineTested) {
        commandLineTested = true;

        QGuiApplicationPrivate *appD = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
        // ### remove port definition when protocol is changed
        int port = 0;
        bool block = false;
        bool ok = false;

        // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block]
        if (!appD->qmljsDebugArgumentsString().isEmpty()) {
            if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
                qWarning() << QString::fromLatin1(
                                  "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                                  "Debugging has not been enabled.").arg(
                                  appD->qmljsDebugArgumentsString());
                return 0;
            }

            QString pluginName;
            if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) {
                int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
                port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
                pluginName = QLatin1String("qmldbg_tcp");
            } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) {
                pluginName = QLatin1String("qmldbg_ost");
                ok = true;
            }

            block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));

            if (ok) {
                server = new QDeclarativeDebugServer();

                QDeclarativeDebugServerConnection *connection
                        = QDeclarativeDebugServerPrivate::loadConnectionPlugin(pluginName);
                if (connection) {
                    server->d_func()->connection = connection;

                    connection->setServer(server);
                    connection->setPort(port, block);
                } else {
                    qWarning() << QString::fromLatin1(
                                      "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                                      "Remote debugger plugin has not been found.").arg(
                                      appD->qmljsDebugArgumentsString());
                }

            } else {
                qWarning() << QString::fromLatin1(
                                  "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                                  "Format is -qmljsdebugger=port:<port>[,block]").arg(
                                  appD->qmljsDebugArgumentsString());
            }
        }
#else
        if (!appD->qmljsDebugArgumentsString().isEmpty()) {
            qWarning() << QString::fromLatin1(
                         "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                         "QtDeclarative is not configured for debugging.").arg(
                         appD->qmljsDebugArgumentsString());
        }
#endif
    }

    return server;
}

QDeclarativeDebugServer::QDeclarativeDebugServer()
    : QObject(*(new QDeclarativeDebugServerPrivate))
{
}

void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
{
    Q_D(QDeclarativeDebugServer);

    QDataStream in(message);
    QString name;

    in >> name;
    if (name == QLatin1String("QDeclarativeDebugServer")) {
        int op = -1;
        in >> op;
        if (op == 0) {
            int version;
            in >> version >> d->clientPlugins;

            // Send the hello answer immediately, since it needs to arrive before
            // the plugins below start sending messages.
            QByteArray helloAnswer;
            {
                QDataStream out(&helloAnswer, QIODevice::WriteOnly);
                out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
            }
            d->connection->send(helloAnswer);

            d->gotHello = true;

            QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
            for (; iter != d->plugins.end(); ++iter) {
                QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
                if (d->clientPlugins.contains(iter.key()))
                    newStatus = QDeclarativeDebugService::Enabled;
                iter.value()->d_func()->status = newStatus;
                iter.value()->statusChanged(newStatus);
            }

            qWarning("QDeclarativeDebugServer: Connection established");

        } else if (op == 1) {

            // Service Discovery
            QStringList oldClientPlugins = d->clientPlugins;
            in >> d->clientPlugins;

            QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
            for (; iter != d->plugins.end(); ++iter) {
                const QString pluginName = iter.key();
                QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
                if (d->clientPlugins.contains(pluginName))
                    newStatus = QDeclarativeDebugService::Enabled;

                if (oldClientPlugins.contains(pluginName)
                        != d->clientPlugins.contains(pluginName)) {
                    iter.value()->d_func()->status = newStatus;
                    iter.value()->statusChanged(newStatus);
                }
            }

        } else {
            qWarning("QDeclarativeDebugServer: Invalid control message %d", op);
            d->connection->disconnect();
            return;
        }

    } else {
        if (d->gotHello) {
            QByteArray message;
            in >> message;

            if (d->waitingForMsgFromService == name) {
                // deliver directly so that it is delivered before waitForMessage is returning.
                d->_q_deliverMessage(name, message);
                d->waitingForMsgSucceeded = true;
            } else {
                // deliver message in next event loop run.
                // Fixes the case that the service does start it's own event loop ...,
                // but the networking code doesn't deliver any new messages because readyRead
                // hasn't returned.
                QMetaObject::invokeMethod(this, "_q_deliverMessage", Qt::QueuedConnection,
                                          Q_ARG(QString, name),
                                          Q_ARG(QByteArray, message));
            }
        } else {
            qWarning("QDeclarativeDebugServer: Invalid hello message");
        }

    }
}

void QDeclarativeDebugServerPrivate::_q_deliverMessage(const QString &serviceName, const QByteArray &message)
{
    QHash<QString, QDeclarativeDebugService *>::Iterator iter = plugins.find(serviceName);
    if (iter == plugins.end()) {
        qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << serviceName;
    } else {
        (*iter)->messageReceived(message);
    }
}

QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const
{
    const Q_D(QDeclarativeDebugServer);
    return d->plugins.values();
}

QStringList QDeclarativeDebugServer::serviceNames() const
{
    const Q_D(QDeclarativeDebugServer);
    return d->plugins.keys();
}

bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service)
{
    Q_D(QDeclarativeDebugServer);
    if (!service || d->plugins.contains(service->name()))
        return false;

    d->plugins.insert(service->name(), service);
    d->advertisePlugins();

    QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
    if (d->clientPlugins.contains(service->name()))
        newStatus = QDeclarativeDebugService::Enabled;
    service->d_func()->status = newStatus;
    service->statusChanged(newStatus);
    return true;
}

bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service)
{
    Q_D(QDeclarativeDebugServer);
    if (!service || !d->plugins.contains(service->name()))
        return false;

    d->plugins.remove(service->name());
    d->advertisePlugins();

    QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
    service->d_func()->server = 0;
    service->d_func()->status = newStatus;
    service->statusChanged(newStatus);
    return true;
}

void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service,
                                          const QByteArray &message)
{
    Q_D(QDeclarativeDebugServer);
    QByteArray msg;
    {
        QDataStream out(&msg, QIODevice::WriteOnly);
        out << service->name() << message;
    }
    d->connection->send(msg);
}

bool QDeclarativeDebugServer::waitForMessage(QDeclarativeDebugService *service)
{
    Q_D(QDeclarativeDebugServer);

    if (!service
            || !d->plugins.contains(service->name())
            || !d->waitingForMsgFromService.isEmpty())
        return false;

    d->waitingForMsgSucceeded = false;
    d->waitingForMsgFromService = service->name();

    do {
        d->connection->waitForMessage();
    } while (!d->waitingForMsgSucceeded);
    d->waitingForMsgFromService.clear();
    return true;
}

QT_END_NAMESPACE

#include "moc_qdeclarativedebugserver_p.cpp"
<commit_msg>Fix compilation with QT_NO_*<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "private/qdeclarativedebugserver_p.h"
#include "private/qdeclarativedebugservice_p.h"
#include "private/qdeclarativedebugservice_p_p.h"
#include "private/qdeclarativeengine_p.h"

#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
#include <QtCore/QStringList>

#include <private/qobject_p.h>
#include <private/qguiapplication_p.h>

QT_BEGIN_NAMESPACE

/*
  QDeclarativeDebug Protocol (Version 1):

  handshake:
    1. Client sends
         "QDeclarativeDebugServer" 0 version pluginNames
       version: an int representing the highest protocol version the client knows
       pluginNames: plugins available on client side
    2. Server sends
         "QDeclarativeDebugClient" 0 version pluginNames
       version: an int representing the highest protocol version the client & server know
       pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
  client plugin advertisement
    1. Client sends
         "QDeclarativeDebugServer" 1 pluginNames
  server plugin advertisement
    1. Server sends
         "QDeclarativeDebugClient" 1 pluginNames
  plugin communication:
       Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
  */

const int protocolVersion = 1;

class QDeclarativeDebugServerPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QDeclarativeDebugServer)
public:
    QDeclarativeDebugServerPrivate();

    void advertisePlugins();

    QDeclarativeDebugServerConnection *connection;
    QHash<QString, QDeclarativeDebugService *> plugins;
    QStringList clientPlugins;
    bool gotHello;
    QString waitingForMsgFromService;
    bool waitingForMsgSucceeded;

private:
    // private slot
    void _q_deliverMessage(const QString &serviceName, const QByteArray &message);
    static QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
};

QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() :
    connection(0),
    gotHello(false),
    waitingForMsgSucceeded(false)
{
}

void QDeclarativeDebugServerPrivate::advertisePlugins()
{
    if (!gotHello)
        return;

    QByteArray message;
    {
        QDataStream out(&message, QIODevice::WriteOnly);
        out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys();
    }
    connection->send(message);
}

QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin(
        const QString &pluginName)
{
#ifndef QT_NO_LIBRARY
    QStringList pluginCandidates;
    const QStringList paths = QCoreApplication::libraryPaths();
    foreach (const QString &libPath, paths) {
        const QDir dir(libPath + QLatin1String("/qmltooling"));
        if (dir.exists()) {
            QStringList plugins(dir.entryList(QDir::Files));
            foreach (const QString &pluginPath, plugins) {
                if (QFileInfo(pluginPath).fileName().contains(pluginName))
                    pluginCandidates << dir.absoluteFilePath(pluginPath);
            }
        }
    }

    foreach (const QString &pluginPath, pluginCandidates) {
        QPluginLoader loader(pluginPath);
        if (!loader.load()) {
            continue;
        }
        QDeclarativeDebugServerConnection *connection = 0;
        if (QObject *instance = loader.instance())
            connection = qobject_cast<QDeclarativeDebugServerConnection*>(instance);

        if (connection)
            return connection;
        loader.unload();
    }
#endif
    return 0;
}

bool QDeclarativeDebugServer::hasDebuggingClient() const
{
    Q_D(const QDeclarativeDebugServer);
    return d->connection
            && d->connection->isConnected()
            && d->gotHello;
}

QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
{
    static bool commandLineTested = false;
    static QDeclarativeDebugServer *server = 0;

    if (!commandLineTested) {
        commandLineTested = true;

        QGuiApplicationPrivate *appD = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
        // ### remove port definition when protocol is changed
        int port = 0;
        bool block = false;
        bool ok = false;

        // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block]
        if (!appD->qmljsDebugArgumentsString().isEmpty()) {
            if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
                qWarning() << QString::fromLatin1(
                                  "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                                  "Debugging has not been enabled.").arg(
                                  appD->qmljsDebugArgumentsString());
                return 0;
            }

            QString pluginName;
            if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) {
                int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
                port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
                pluginName = QLatin1String("qmldbg_tcp");
            } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) {
                pluginName = QLatin1String("qmldbg_ost");
                ok = true;
            }

            block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));

            if (ok) {
                server = new QDeclarativeDebugServer();

                QDeclarativeDebugServerConnection *connection
                        = QDeclarativeDebugServerPrivate::loadConnectionPlugin(pluginName);
                if (connection) {
                    server->d_func()->connection = connection;

                    connection->setServer(server);
                    connection->setPort(port, block);
                } else {
                    qWarning() << QString::fromLatin1(
                                      "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                                      "Remote debugger plugin has not been found.").arg(
                                      appD->qmljsDebugArgumentsString());
                }

            } else {
                qWarning() << QString::fromLatin1(
                                  "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                                  "Format is -qmljsdebugger=port:<port>[,block]").arg(
                                  appD->qmljsDebugArgumentsString());
            }
        }
#else
        if (!appD->qmljsDebugArgumentsString().isEmpty()) {
            qWarning() << QString::fromLatin1(
                         "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
                         "QtDeclarative is not configured for debugging.").arg(
                         appD->qmljsDebugArgumentsString());
        }
#endif
    }

    return server;
}

QDeclarativeDebugServer::QDeclarativeDebugServer()
    : QObject(*(new QDeclarativeDebugServerPrivate))
{
}

void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
{
    Q_D(QDeclarativeDebugServer);

    QDataStream in(message);
    QString name;

    in >> name;
    if (name == QLatin1String("QDeclarativeDebugServer")) {
        int op = -1;
        in >> op;
        if (op == 0) {
            int version;
            in >> version >> d->clientPlugins;

            // Send the hello answer immediately, since it needs to arrive before
            // the plugins below start sending messages.
            QByteArray helloAnswer;
            {
                QDataStream out(&helloAnswer, QIODevice::WriteOnly);
                out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
            }
            d->connection->send(helloAnswer);

            d->gotHello = true;

            QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
            for (; iter != d->plugins.end(); ++iter) {
                QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
                if (d->clientPlugins.contains(iter.key()))
                    newStatus = QDeclarativeDebugService::Enabled;
                iter.value()->d_func()->status = newStatus;
                iter.value()->statusChanged(newStatus);
            }

            qWarning("QDeclarativeDebugServer: Connection established");

        } else if (op == 1) {

            // Service Discovery
            QStringList oldClientPlugins = d->clientPlugins;
            in >> d->clientPlugins;

            QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
            for (; iter != d->plugins.end(); ++iter) {
                const QString pluginName = iter.key();
                QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
                if (d->clientPlugins.contains(pluginName))
                    newStatus = QDeclarativeDebugService::Enabled;

                if (oldClientPlugins.contains(pluginName)
                        != d->clientPlugins.contains(pluginName)) {
                    iter.value()->d_func()->status = newStatus;
                    iter.value()->statusChanged(newStatus);
                }
            }

        } else {
            qWarning("QDeclarativeDebugServer: Invalid control message %d", op);
            d->connection->disconnect();
            return;
        }

    } else {
        if (d->gotHello) {
            QByteArray message;
            in >> message;

            if (d->waitingForMsgFromService == name) {
                // deliver directly so that it is delivered before waitForMessage is returning.
                d->_q_deliverMessage(name, message);
                d->waitingForMsgSucceeded = true;
            } else {
                // deliver message in next event loop run.
                // Fixes the case that the service does start it's own event loop ...,
                // but the networking code doesn't deliver any new messages because readyRead
                // hasn't returned.
                QMetaObject::invokeMethod(this, "_q_deliverMessage", Qt::QueuedConnection,
                                          Q_ARG(QString, name),
                                          Q_ARG(QByteArray, message));
            }
        } else {
            qWarning("QDeclarativeDebugServer: Invalid hello message");
        }

    }
}

void QDeclarativeDebugServerPrivate::_q_deliverMessage(const QString &serviceName, const QByteArray &message)
{
    QHash<QString, QDeclarativeDebugService *>::Iterator iter = plugins.find(serviceName);
    if (iter == plugins.end()) {
        qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << serviceName;
    } else {
        (*iter)->messageReceived(message);
    }
}

QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const
{
    const Q_D(QDeclarativeDebugServer);
    return d->plugins.values();
}

QStringList QDeclarativeDebugServer::serviceNames() const
{
    const Q_D(QDeclarativeDebugServer);
    return d->plugins.keys();
}

bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service)
{
    Q_D(QDeclarativeDebugServer);
    if (!service || d->plugins.contains(service->name()))
        return false;

    d->plugins.insert(service->name(), service);
    d->advertisePlugins();

    QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
    if (d->clientPlugins.contains(service->name()))
        newStatus = QDeclarativeDebugService::Enabled;
    service->d_func()->status = newStatus;
    service->statusChanged(newStatus);
    return true;
}

bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service)
{
    Q_D(QDeclarativeDebugServer);
    if (!service || !d->plugins.contains(service->name()))
        return false;

    d->plugins.remove(service->name());
    d->advertisePlugins();

    QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
    service->d_func()->server = 0;
    service->d_func()->status = newStatus;
    service->statusChanged(newStatus);
    return true;
}

void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service,
                                          const QByteArray &message)
{
    Q_D(QDeclarativeDebugServer);
    QByteArray msg;
    {
        QDataStream out(&msg, QIODevice::WriteOnly);
        out << service->name() << message;
    }
    d->connection->send(msg);
}

bool QDeclarativeDebugServer::waitForMessage(QDeclarativeDebugService *service)
{
    Q_D(QDeclarativeDebugServer);

    if (!service
            || !d->plugins.contains(service->name())
            || !d->waitingForMsgFromService.isEmpty())
        return false;

    d->waitingForMsgSucceeded = false;
    d->waitingForMsgFromService = service->name();

    do {
        d->connection->waitForMessage();
    } while (!d->waitingForMsgSucceeded);
    d->waitingForMsgFromService.clear();
    return true;
}

QT_END_NAMESPACE

#include "moc_qdeclarativedebugserver_p.cpp"
<|endoftext|>


<commit_before>#include <Halide.h>
#include <math.h>
#include <sys/time.h>

using namespace Halide;

// Make some functions for turning types into strings
template<typename A>
const char *string_of_type();

#define DECL_SOT(name)                                          \
    template<>                                                  \
    const char *string_of_type<name>() {return #name;}

DECL_SOT(uint8_t);
DECL_SOT(int8_t);
DECL_SOT(uint16_t);
DECL_SOT(int16_t);
DECL_SOT(uint32_t);
DECL_SOT(int32_t);
DECL_SOT(float);
DECL_SOT(double);

double currentTime() {
    timeval t;
    gettimeofday(&t, NULL);
    return t.tv_sec * 1000.0 + t.tv_usec / 1000.0f;
}

template<typename A>
A mod(A x, A y);

template<>
float mod(float x, float y) {
    return fmod(x, y);
}

template<>
double mod(double x, double y) {
    return fmod(x, y);
}

template<typename A>
A mod(A x, A y) {
    return x % y;
}

template<typename A>
bool test(int vec_width) {
    const int W = 3200;
    const int H = 16;

    printf("Testing %s\n", string_of_type<A>());

    Image<A> input(W+16, H+16);
    for (int y = 0; y < H+16; y++) {
        for (int x = 0; x < W+16; x++) {
            input(x, y) = (A)(rand()*0.125 + 1.0);
        }
    }
    Var x, y;

    // Add
    printf("Add\n");
    Func f1;
    f1(x, y) = input(x, y) + input(x+1, y);
    f1.vectorize(x, vec_width);
    Image<A> im1 = f1.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) + input(x+1, y);
            if (im1(x, y) != correct) {
                printf("im1(%d, %d) = %f instead of %f\n", x, y, (double)(im1(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Sub
    printf("Subtract\n");
    Func f2;
    f2(x, y) = input(x, y) - input(x+1, y);
    f2.vectorize(x, vec_width);
    Image<A> im2 = f2.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) - input(x+1, y);
            if (im2(x, y) != correct) {
                printf("im2(%d, %d) = %f instead of %f\n", x, y, (double)(im2(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Mul
    printf("Multiply\n");
    Func f3;
    f3(x, y) = input(x, y) * input(x+1, y);
    f3.vectorize(x, vec_width);
    Image<A> im3 = f3.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) * input(x+1, y);
            if (im3(x, y) != correct) {
                printf("im3(%d, %d) = %f instead of %f\n", x, y, (double)(im3(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // select
    printf("Select\n");
    Func f4;
    f4(x, y) = select(input(x, y) > input(x+1, y), input(x+2, y), input(x+3, y));
    f4.vectorize(x, vec_width);
    Image<A> im4 = f4.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) > input(x+1, y) ? input(x+2, y) : input(x+3, y);
            if (im4(x, y) != correct) {
                printf("im4(%d, %d) = %f instead of %f\n", x, y, (double)(im4(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Gather
    printf("Gather\n");
    Func f5;
    Expr xCoord = clamp(cast<int>(input(x, y)), 0, W-1);
    Expr yCoord = clamp(cast<int>(input(x+1, y)), 0, H-1);
    f5(x, y) = input(xCoord, yCoord);
    f5.vectorize(x, vec_width);
    Image<A> im5 = f5.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            int xCoord = (int)(input(x, y));
            if (xCoord >= W) xCoord = W-1;
            if (xCoord < 0) xCoord = 0;

            int yCoord = (int)(input(x+1, y));
            if (yCoord >= H) yCoord = H-1;
            if (yCoord < 0) yCoord = 0;

            A correct = input(xCoord, yCoord);

            if (im5(x, y) != correct) {
                printf("im5(%d, %d) = %f instead of %f\n", x, y, (double)(im5(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Scatter
    printf("Scatter\n");
    Func f6;
    RDom i(0, H);
    // Set one entry in each row high
    xCoord = clamp(cast<int>(input(2*i, i)), 0, W-1);
    f6(x, y) = 0;
    f6(xCoord, i) = 1;

    f6.vectorize(x, vec_width);

    Image<int> im6 = f6.realize(W, H);

    for (int y = 0; y < H; y++) {
        int xCoord = (int)(input(2*y, y));
        if (xCoord >= W) xCoord = W-1;
        if (xCoord < 0) xCoord = 0;
        for (int x = 0; x < W; x++) {
            int correct = x == xCoord ? 1 : 0;
            if (im6(x, y) != correct) {
                printf("im6(%d, %d) = %d instead of %d\n", x, y, im6(x, y), correct);
                return false;
            }
        }
    }

    // Min/max
    printf("Min/max\n");
    Func f7;
    f7(x, y) = clamp(input(x, y), cast<A>(10), cast<A>(20));
    f7.vectorize(x, vec_width);
    Image<A> im7 = f7.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            if (im7(x, y) < (A)10 || im7(x, y) > (A)20) {
                printf("im7(%d, %d) = %f instead of %f\n", x, y, (double)(im7(x, y)));
                return false;
            }
        }
    }

    // Extern function call
    printf("External call to pow\n");
    Func f8;
    f8(x, y) = pow(1.1f, cast<float>(input(x, y)));
    f8.vectorize(x, vec_width);
    Image<float> im8 = f8.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            float correct = powf(1.1f, (float)input(x, y));
            if (im8(x, y) != correct) {
                printf("im8(%d, %d) = %f instead of %f\n", x, y, im8(x, y));
                return false;
            }
        }
    }

    // Div
    printf("Division\n");
    Func f9;
    f9(x, y) = input(x, y) / clamp(input(x+1, y), cast<A>(1), cast<A>(3));
    f9.vectorize(x, vec_width);
    Image<A> im9 = f9.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A clamped = input(x+1, y);
            if (clamped < (A)1) clamped = (A)1;
            if (clamped > (A)3) clamped = (A)3;
            A correct = input(x, y) / clamped;
            if (im9(x, y) != correct) {
                printf("im9(%d, %d) = %f instead of %f\n", x, y, (double)(im9(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Divide by small constants
    printf("Dividing by small constants\n");
    for (int c = 2; c < 16; c++) {
	Func f10;
	f10(x, y) = input(x, y) / c;
	f10.vectorize(x, vec_width);
	Image<A> im10 = f10.realize(W, H);

	for (int y = 0; y < H; y++) {
	    for (int x = 0; x < W; x++) {
		A correct = input(x, y) / c;
		if (im10(x, y) != correct) {
		    printf("im10(%d, %d) = %f/%d = %f instead of %f\n", x, y,
			   (double)(input(x, y)), c,
			   (double)(im10(x, y)),
			   (double)(correct));
		    printf("Error when dividing by %d\n", c);
		    return false;
		}
	    }
	}
    }

    // Interleave
    printf("Interleaving store\n");
    Func f11;
    f11(x, y) = select((x%2)==0, input(x/2, y), input(x/2, y+1));
    f11.vectorize(x, vec_width);
    Image<A> im11 = f11.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = ((x%2)==0) ? input(x/2, y) : input(x/2, y+1);
            if (im11(x, y) != correct) {
                printf("im11(%d, %d) = %f instead of %f\n", x, y, (double)(im11(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Reverse
    printf("Reversing\n");
    Func f12;
    f12(x, y) = input(W-1-x, H-1-y);
    f12.vectorize(x, vec_width);
    Image<A> im12 = f12.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(W-1-x, H-1-y);
            if (im12(x, y) != correct) {
                printf("im12(%d, %d) = %f instead of %f\n", x, y, (double)(im12(x, y)), (double)(correct));
                return false;
            }
        }
    }

    return true;
}

int main(int argc, char **argv) {

    bool ok = true;

    // Only native vector widths - llvm doesn't handle others well
    ok = ok && test<float>(4);
    ok = ok && test<float>(8);
    ok = ok && test<double>(2);
    ok = ok && test<uint8_t>(16);
    ok = ok && test<int8_t>(16);
    ok = ok && test<uint16_t>(8);
    ok = ok && test<int16_t>(8);
    ok = ok && test<uint32_t>(4);
    ok = ok && test<int32_t>(4);

    if (!ok) return -1;
    printf("Success!\n");
    return 0;
}
<commit_msg>Added test for known alignment unaligned load<commit_after>#include <Halide.h>
#include <math.h>
#include <sys/time.h>

using namespace Halide;

// Make some functions for turning types into strings
template<typename A>
const char *string_of_type();

#define DECL_SOT(name)                                          \
    template<>                                                  \
    const char *string_of_type<name>() {return #name;}

DECL_SOT(uint8_t);
DECL_SOT(int8_t);
DECL_SOT(uint16_t);
DECL_SOT(int16_t);
DECL_SOT(uint32_t);
DECL_SOT(int32_t);
DECL_SOT(float);
DECL_SOT(double);

double currentTime() {
    timeval t;
    gettimeofday(&t, NULL);
    return t.tv_sec * 1000.0 + t.tv_usec / 1000.0f;
}

template<typename A>
A mod(A x, A y);

template<>
float mod(float x, float y) {
    return fmod(x, y);
}

template<>
double mod(double x, double y) {
    return fmod(x, y);
}

template<typename A>
A mod(A x, A y) {
    return x % y;
}

template<typename A>
bool test(int vec_width) {
    const int W = 3200;
    const int H = 16;

    printf("Testing %s\n", string_of_type<A>());

    Image<A> input(W+16, H+16);
    for (int y = 0; y < H+16; y++) {
        for (int x = 0; x < W+16; x++) {
            input(x, y) = (A)(rand()*0.125 + 1.0);
        }
    }
    Var x, y;

    // Add
    printf("Add\n");
    Func f1;
    f1(x, y) = input(x, y) + input(x+1, y);
    f1.vectorize(x, vec_width);
    Image<A> im1 = f1.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) + input(x+1, y);
            if (im1(x, y) != correct) {
                printf("im1(%d, %d) = %f instead of %f\n", x, y, (double)(im1(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Sub
    printf("Subtract\n");
    Func f2;
    f2(x, y) = input(x, y) - input(x+1, y);
    f2.vectorize(x, vec_width);
    Image<A> im2 = f2.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) - input(x+1, y);
            if (im2(x, y) != correct) {
                printf("im2(%d, %d) = %f instead of %f\n", x, y, (double)(im2(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Mul
    printf("Multiply\n");
    Func f3;
    f3(x, y) = input(x, y) * input(x+1, y);
    f3.vectorize(x, vec_width);
    Image<A> im3 = f3.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) * input(x+1, y);
            if (im3(x, y) != correct) {
                printf("im3(%d, %d) = %f instead of %f\n", x, y, (double)(im3(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // select
    printf("Select\n");
    Func f4;
    f4(x, y) = select(input(x, y) > input(x+1, y), input(x+2, y), input(x+3, y));
    f4.vectorize(x, vec_width);
    Image<A> im4 = f4.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x, y) > input(x+1, y) ? input(x+2, y) : input(x+3, y);
            if (im4(x, y) != correct) {
                printf("im4(%d, %d) = %f instead of %f\n", x, y, (double)(im4(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Gather
    printf("Gather\n");
    Func f5;
    Expr xCoord = clamp(cast<int>(input(x, y)), 0, W-1);
    Expr yCoord = clamp(cast<int>(input(x+1, y)), 0, H-1);
    f5(x, y) = input(xCoord, yCoord);
    f5.vectorize(x, vec_width);
    Image<A> im5 = f5.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            int xCoord = (int)(input(x, y));
            if (xCoord >= W) xCoord = W-1;
            if (xCoord < 0) xCoord = 0;

            int yCoord = (int)(input(x+1, y));
            if (yCoord >= H) yCoord = H-1;
            if (yCoord < 0) yCoord = 0;

            A correct = input(xCoord, yCoord);

            if (im5(x, y) != correct) {
                printf("im5(%d, %d) = %f instead of %f\n", x, y, (double)(im5(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Scatter
    printf("Scatter\n");
    Func f6;
    RDom i(0, H);
    // Set one entry in each row high
    xCoord = clamp(cast<int>(input(2*i, i)), 0, W-1);
    f6(x, y) = 0;
    f6(xCoord, i) = 1;

    f6.vectorize(x, vec_width);

    Image<int> im6 = f6.realize(W, H);

    for (int y = 0; y < H; y++) {
        int xCoord = (int)(input(2*y, y));
        if (xCoord >= W) xCoord = W-1;
        if (xCoord < 0) xCoord = 0;
        for (int x = 0; x < W; x++) {
            int correct = x == xCoord ? 1 : 0;
            if (im6(x, y) != correct) {
                printf("im6(%d, %d) = %d instead of %d\n", x, y, im6(x, y), correct);
                return false;
            }
        }
    }

    // Min/max
    printf("Min/max\n");
    Func f7;
    f7(x, y) = clamp(input(x, y), cast<A>(10), cast<A>(20));
    f7.vectorize(x, vec_width);
    Image<A> im7 = f7.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            if (im7(x, y) < (A)10 || im7(x, y) > (A)20) {
                printf("im7(%d, %d) = %f instead of %f\n", x, y, (double)(im7(x, y)));
                return false;
            }
        }
    }

    // Extern function call
    printf("External call to pow\n");
    Func f8;
    f8(x, y) = pow(1.1f, cast<float>(input(x, y)));
    f8.vectorize(x, vec_width);
    Image<float> im8 = f8.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            float correct = powf(1.1f, (float)input(x, y));
            if (im8(x, y) != correct) {
                printf("im8(%d, %d) = %f instead of %f\n", x, y, im8(x, y));
                return false;
            }
        }
    }

    // Div
    printf("Division\n");
    Func f9;
    f9(x, y) = input(x, y) / clamp(input(x+1, y), cast<A>(1), cast<A>(3));
    f9.vectorize(x, vec_width);
    Image<A> im9 = f9.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A clamped = input(x+1, y);
            if (clamped < (A)1) clamped = (A)1;
            if (clamped > (A)3) clamped = (A)3;
            A correct = input(x, y) / clamped;
            if (im9(x, y) != correct) {
                printf("im9(%d, %d) = %f instead of %f\n", x, y, (double)(im9(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Divide by small constants
    printf("Dividing by small constants\n");
    for (int c = 2; c < 16; c++) {
	Func f10;
	f10(x, y) = input(x, y) / c;
	f10.vectorize(x, vec_width);
	Image<A> im10 = f10.realize(W, H);

	for (int y = 0; y < H; y++) {
	    for (int x = 0; x < W; x++) {
		A correct = input(x, y) / c;
		if (im10(x, y) != correct) {
		    printf("im10(%d, %d) = %f/%d = %f instead of %f\n", x, y,
			   (double)(input(x, y)), c,
			   (double)(im10(x, y)),
			   (double)(correct));
		    printf("Error when dividing by %d\n", c);
		    return false;
		}
	    }
	}
    }

    // Interleave
    printf("Interleaving store\n");
    Func f11;
    f11(x, y) = select((x%2)==0, input(x/2, y), input(x/2, y+1));
    f11.vectorize(x, vec_width);
    Image<A> im11 = f11.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = ((x%2)==0) ? input(x/2, y) : input(x/2, y+1);
            if (im11(x, y) != correct) {
                printf("im11(%d, %d) = %f instead of %f\n", x, y, (double)(im11(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Reverse
    printf("Reversing\n");
    Func f12;
    f12(x, y) = input(W-1-x, H-1-y);
    f12.vectorize(x, vec_width);
    Image<A> im12 = f12.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(W-1-x, H-1-y);
            if (im12(x, y) != correct) {
                printf("im12(%d, %d) = %f instead of %f\n", x, y, (double)(im12(x, y)), (double)(correct));
                return false;
            }
        }
    }

    // Unaligned load with known shift
    printf("Unaligned load\n");
    Func f13;
    f13(x, y) = input(x+3, y);
    f13.vectorize(x, vec_width);
    Image<A> im13 = f13.realize(W, H);

    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) {
            A correct = input(x+3, y);
            if (im13(x, y) != correct) {
                printf("im13(%d, %d) = %f instead of %d\n", x, y, (double)(im13(x, y)), (double)(correct));
            }
        }
    }

    return true;
}

int main(int argc, char **argv) {

    bool ok = true;

    // Only native vector widths - llvm doesn't handle others well
    ok = ok && test<float>(4);
    ok = ok && test<float>(8);
    ok = ok && test<double>(2);
    ok = ok && test<uint8_t>(16);
    ok = ok && test<int8_t>(16);
    ok = ok && test<uint16_t>(8);
    ok = ok && test<int16_t>(8);
    ok = ok && test<uint32_t>(4);
    ok = ok && test<int32_t>(4);

    if (!ok) return -1;
    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>///
/// @file  pi_deleglise_rivat_parallel3.cpp
/// @brief Parallel implementation of the Deleglise-Rivat prime
///        counting algorithm. This implementation is identical to
///        pi_deleglise_rivat_parallel2(x) but uses 128-bit integers.
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <int128.hpp>
#include <S1.hpp>
#include "S2.hpp"

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>

using namespace std;
using namespace primecount;

namespace {

/// alpha is a tuning factor which should grow like (log(x))^3
/// for the Deleglise-Rivat prime counting algorithm.
///
double compute_alpha(int128_t x)
{
  double d = (double) x;
  double alpha = (get_alpha() >= 1) ? get_alpha() : log(d) * log(d) * log(d) / 1200;
  return in_between(1, alpha, iroot<6>(x));
}

/// Calculate the contribution of the special leaves.
/// @pre y > 0 && c > 1
///
int128_t S2(int128_t x,
            int64_t y,
            int64_t z,
            int64_t c,
            int128_t s2_approx,
            int threads)
{
  int128_t s2_trivial = S2_trivial(x, y, z, c, threads);
  int128_t s2_easy = S2_easy(x, y, z, c, threads);
  int128_t s2_hard_approx = s2_approx - (s2_trivial + s2_easy);
  int128_t s2_hard = S2_hard(x, y, z, c, s2_hard_approx, threads);
  int128_t s2 = s2_trivial + s2_easy + s2_hard;

  return s2;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int128_t pi_deleglise_rivat_parallel3(int128_t x, int threads)
{
  if (x < 2)
    return 0;

  if (x > to_maxint(primecount::max()))
    throw primecount_error("pi(x): x must be <= " + max());

  double alpha = compute_alpha(x);
  int64_t y = (int64_t) (alpha * iroot<3>(x));
  int64_t z = (int64_t) (x / y);
  int64_t pi_y = pi_legendre(y, 1);
  int64_t c = min(pi_y, PhiTiny::max_a());

  if (print_status())
  {
    cout << endl;
    cout << "=== pi_deleglise_rivat_parallel3(x) ===" << endl;
    cout << "pi(x) = S1 + S2 + pi(y) - 1 - P2" << endl;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "alpha = " << fixed << setprecision(3) << alpha << endl;
    cout << "c = " << c << endl;
    cout << "threads = " << validate_threads(threads) << endl;
  }

  int128_t p2 = P2(x, y, threads);
  int128_t s1 = S1(x, y, c, threads);
  int128_t s2_approx = S2_approx(x, pi_y, p2, s1);
  int128_t s2 = S2(x, y, z, c, s2_approx, threads);
  int128_t phi = s1 + s2;
  int128_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace
<commit_msg>Remove unused header<commit_after>///
/// @file  pi_deleglise_rivat_parallel3.cpp
/// @brief Parallel implementation of the Deleglise-Rivat prime
///        counting algorithm. This implementation is identical to
///        pi_deleglise_rivat_parallel2(x) but uses 128-bit integers.
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <int128.hpp>
#include <S1.hpp>
#include "S2.hpp"

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <iomanip>

using namespace std;
using namespace primecount;

namespace {

/// alpha is a tuning factor which should grow like (log(x))^3
/// for the Deleglise-Rivat prime counting algorithm.
///
double compute_alpha(int128_t x)
{
  double d = (double) x;
  double alpha = (get_alpha() >= 1) ? get_alpha() : log(d) * log(d) * log(d) / 1200;
  return in_between(1, alpha, iroot<6>(x));
}

/// Calculate the contribution of the special leaves.
/// @pre y > 0 && c > 1
///
int128_t S2(int128_t x,
            int64_t y,
            int64_t z,
            int64_t c,
            int128_t s2_approx,
            int threads)
{
  int128_t s2_trivial = S2_trivial(x, y, z, c, threads);
  int128_t s2_easy = S2_easy(x, y, z, c, threads);
  int128_t s2_hard_approx = s2_approx - (s2_trivial + s2_easy);
  int128_t s2_hard = S2_hard(x, y, z, c, s2_hard_approx, threads);
  int128_t s2 = s2_trivial + s2_easy + s2_hard;

  return s2;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int128_t pi_deleglise_rivat_parallel3(int128_t x, int threads)
{
  if (x < 2)
    return 0;

  if (x > to_maxint(primecount::max()))
    throw primecount_error("pi(x): x must be <= " + max());

  double alpha = compute_alpha(x);
  int64_t y = (int64_t) (alpha * iroot<3>(x));
  int64_t z = (int64_t) (x / y);
  int64_t pi_y = pi_legendre(y, 1);
  int64_t c = min(pi_y, PhiTiny::max_a());

  if (print_status())
  {
    cout << endl;
    cout << "=== pi_deleglise_rivat_parallel3(x) ===" << endl;
    cout << "pi(x) = S1 + S2 + pi(y) - 1 - P2" << endl;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "alpha = " << fixed << setprecision(3) << alpha << endl;
    cout << "c = " << c << endl;
    cout << "threads = " << validate_threads(threads) << endl;
  }

  int128_t p2 = P2(x, y, threads);
  int128_t s1 = S1(x, y, c, threads);
  int128_t s2_approx = S2_approx(x, pi_y, p2, s1);
  int128_t s2 = S2(x, y, z, c, s2_approx, threads);
  int128_t phi = s1 + s2;
  int128_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace
<|endoftext|>


<commit_before>/**
 * Description: Edit distance (Find the levenstein distance between two strings)
 * Usage: solve O(NM)
 * Source: https://github.com/dragonslayerx
 */

#define MAX 2050
int edist[2][MAX];

class Edist {
    public:
		int solve(string &S1, string &S2){
			int last = 0, current = 1;
			for (int i = 0; i <= S1.size(); i++){
				for (int j = 0; j <= S2.size(); j++){
					if (i == 0) edist[current][j] = j;
					else if (j == 0) edist[current][j] = i;
					else {
						edist[current][j] = min(edist[last][j] + 1, edist[current][j-1]+1);
						if (S1[i-1] == S2[j-1]) {
							edist[current][j] = min(edist[current][j], edist[last][j-1]);
						} else {
							edist[current][j] = min(edist[current][j], edist[last][j-1] + 1);
						}
					}
				}
				swap(last, current);
			}
			return edist[last][S2.size()];
		}
};
<commit_msg>Edit Distance<commit_after>/**
 * Description: Edit distance (Find the levenstein distance between two strings)
 * Usage: solve O(NM)
 * Source: https://github.com/dragonslayerx
 */

int d[2][1005];
int solve(string &s, string &t){
    int prev = 0, current = 1;
    for (int i = 0; i <= s.size(); i++){
        for (int j = 0; j <= t.size(); j++){
            if (i == 0) d[current][j]=j;
            else if (j == 0) d[current][j]=i;
            else {
                d[current][j] = min(d[prev][j]+1, d[current][j-1]+1);
                if (s[i-1]==t[j-1]) {
                    d[current][j] = min(d[current][j], d[prev][j-1]);
                } else {
                    d[current][j] = min(d[current][j], d[prev][j-1]+1);
                }
            }
        }
        swap(prev, current);
    }
    return d[prev][t.size()];
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppVCardManager.h"
#include "QXmppStream.h"
#include "QXmppUtils.h"

QXmppVCardManager::QXmppVCardManager(QXmppStream* stream, QObject *parent)
    : QObject(parent),
    m_stream(stream),
    m_isClientVCardReceived(false)
{
    bool check = QObject::connect(m_stream, SIGNAL(vCardIqReceived(const QXmppVCard&)),
        this, SLOT(vCardIqReceived(const QXmppVCard&)));
    Q_ASSERT(check);
    Q_UNUSED(check);
}

/// This function requests the server for vCard of the specified jid.
/// Once received the signal vCardIqReceived() is emmitted.
///
/// \param jid Jid of the specific entry in the roster
///
void QXmppVCardManager::requestVCard(const QString& jid)
{
    QXmppVCard vcardIq(jid);
    m_stream->sendPacket(vcardIq);
}

void QXmppVCardManager::vCardIqReceived(const QXmppVCard& vcard)
{
    // self vCard received
    if(vcard.from().isEmpty())
    {
        m_clientVCard = vcard;
        m_isClientVCardReceived = true;
        emit clientVCardReceived();
    }

    emit vCardReceived(vcard);
}

/// Returns the vCard of the connected client.
///
/// \return QXmppVCard
///
const QXmppVCard& QXmppVCardManager::clientVCard() const
{
    return m_clientVCard;
}

/// Sets the vCard of the connected client.
///
/// \param clientVCard QXmppVCard
///
void QXmppVCardManager::setClientVCard(const QXmppVCard& clientVCard)
{
    m_clientVCard = clientVCard;
    m_clientVCard.setTo("");
    m_clientVCard.setFrom("");
    m_clientVCard.setType(QXmppIq::Set);
    m_stream->sendPacket(m_clientVCard);
}

/// This function requests the server for vCard of the connected user itself.
/// Once received the signal clientVCardReceived() is emmitted. Received vCard
/// can be get using clientVCard().
void QXmppVCardManager::requestClientVCard()
{
    requestVCard();
}

/// Returns true if vCard of the connected client has been
/// received else false.
///
/// \return bool
///
bool QXmppVCardManager::isClientVCardReceived()
{
    return m_isClientVCardReceived;
}

<commit_msg>typo vCardIqReceived() -> vCardReceived()<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppVCardManager.h"
#include "QXmppStream.h"
#include "QXmppUtils.h"

QXmppVCardManager::QXmppVCardManager(QXmppStream* stream, QObject *parent)
    : QObject(parent),
    m_stream(stream),
    m_isClientVCardReceived(false)
{
    bool check = QObject::connect(m_stream, SIGNAL(vCardIqReceived(const QXmppVCard&)),
        this, SLOT(vCardIqReceived(const QXmppVCard&)));
    Q_ASSERT(check);
    Q_UNUSED(check);
}

/// This function requests the server for vCard of the specified jid.
/// Once received the signal vCardReceived() is emmitted.
///
/// \param jid Jid of the specific entry in the roster
///
void QXmppVCardManager::requestVCard(const QString& jid)
{
    QXmppVCard vcardIq(jid);
    m_stream->sendPacket(vcardIq);
}

void QXmppVCardManager::vCardIqReceived(const QXmppVCard& vcard)
{
    // self vCard received
    if(vcard.from().isEmpty())
    {
        m_clientVCard = vcard;
        m_isClientVCardReceived = true;
        emit clientVCardReceived();
    }

    emit vCardReceived(vcard);
}

/// Returns the vCard of the connected client.
///
/// \return QXmppVCard
///
const QXmppVCard& QXmppVCardManager::clientVCard() const
{
    return m_clientVCard;
}

/// Sets the vCard of the connected client.
///
/// \param clientVCard QXmppVCard
///
void QXmppVCardManager::setClientVCard(const QXmppVCard& clientVCard)
{
    m_clientVCard = clientVCard;
    m_clientVCard.setTo("");
    m_clientVCard.setFrom("");
    m_clientVCard.setType(QXmppIq::Set);
    m_stream->sendPacket(m_clientVCard);
}

/// This function requests the server for vCard of the connected user itself.
/// Once received the signal clientVCardReceived() is emmitted. Received vCard
/// can be get using clientVCard().
void QXmppVCardManager::requestClientVCard()
{
    requestVCard();
}

/// Returns true if vCard of the connected client has been
/// received else false.
///
/// \return bool
///
bool QXmppVCardManager::isClientVCardReceived()
{
    return m_isClientVCardReceived;
}

<|endoftext|>


<commit_before>
/**
 * This file is part of the boostcache package.
 *
 * (c) Azat Khuzhin <a3at.mail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#include "jsvm.h"
#include "util/log.h"
#include "config.h" /** HAVE_* */

/**
 * XXX: get rid of support for old v8
 */

namespace Js
{
#ifdef HAVE_V8_FUNCTIONCALLBACKINFO
    typedef ::v8::FunctionCallbackInfo<::v8::Value> Args;

    std::string logArgs2String(const Args &args)
    {
        std::string message;
        for (int i = 0; i < args.Length(); i++) {
            ::v8::HandleScope scope(args.GetIsolate());
            ::v8::String::Utf8Value str(args[i]);
            message += *str;
        }
        return message;
    }
    void log(const Args &args)
    {
        LOG(info) << logArgs2String(args);
    }
    void error(const Args &args)
    {
        LOG(error) << logArgs2String(args);
    }
#else
    typedef ::v8::Arguments Args;

    std::string logArgs2String(const Args &args)
    {
        std::string message;
        for (int i = 0; i < args.Length(); i++) {
            ::v8::HandleScope scope;
            ::v8::String::Utf8Value str(args[i]);
            message += *str;
        }
        return message;
    }
    ::v8::Handle<::v8::Value> log(const Args &args)
    {
        LOG(info) << logArgs2String(args);
        return v8::Handle<v8::Value>();
    }
    ::v8::Handle<::v8::Value> error(const Args &args)
    {
        LOG(error) << logArgs2String(args);
        return v8::Handle<v8::Value>();
    }
#endif
}

namespace {
#ifdef HAVE_V8_WITH_MOST_CONSTRUCTORS_ISOLATE
    v8::Local<v8::String> newUtf8String(const char *data)
    {
        return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), data);
    }
#else
    v8::Local<v8::String> newUtf8String(const char *data)
    {
        return v8::String::New(data);
    }
#endif
}

JsVm::JsVm(const std::string &code)
    : m_isolate(v8::Isolate::GetCurrent())
    , m_locker(m_isolate)
    , m_global(v8::ObjectTemplate::New())
{
    v8::Handle<v8::ObjectTemplate> console = v8::ObjectTemplate::New();
    m_global->Set(newUtf8String("console"), console);

    console->Set(newUtf8String("log"),
                 v8::FunctionTemplate::New(&Js::log));
    console->Set(newUtf8String("error"),
                 v8::FunctionTemplate::New(&Js::error));

    /**
     * We can't do this inside initialization list, since we are modifying
     * "m_global", and during ths gc can update references to it, since we are
     * adding _properties_ to it.
     *
     * And also to avoid Context::Scope for every call(), just enter context
     * here, since this module already provides "box" for executing
     * user-specific code in current thread.
     */
    m_context = v8::Context::New(NULL, m_global);
    m_context->Enter();

    m_source = newUtf8String(code.c_str());
}
JsVm::~JsVm()
{
    m_context->Exit();
}

bool JsVm::init()
{
    v8::Handle<v8::Script> script = v8::Script::Compile(m_source);
    if (!*script) {
        fillTryCatch();
        return false;
    }

    v8::Handle<v8::Value> sourceResult = script->Run();
    if (sourceResult.IsEmpty()) {
        fillTryCatch();
        return false;
    }

    m_function = v8::Handle<v8::Function>::Cast(sourceResult);
    return true;
}

void JsVm::call(const Db::Interface::Key &key, const Db::Interface::Value &value)
{
    v8::Local<v8::Value> args[] = {
        newUtf8String(key.c_str()),
        newUtf8String(value.c_str())
    };

    m_function->Call(m_context->Global(), 2, args);
}

void JsVm::fillTryCatch()
{
    v8::Handle<v8::Value> exception = m_trycatch.Exception();
    v8::String::AsciiValue exceptionMessage(exception);
    LOG(error) << *exceptionMessage;
}
<commit_msg>jsvm: adopt v8::FunctionTemplate::New for HAVE_V8_WITH_MOST_CONSTRUCTORS_ISOLATE<commit_after>
/**
 * This file is part of the boostcache package.
 *
 * (c) Azat Khuzhin <a3at.mail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#include "jsvm.h"
#include "util/log.h"
#include "config.h" /** HAVE_* */

/**
 * XXX: get rid of support for old v8
 */

namespace Js
{
#ifdef HAVE_V8_FUNCTIONCALLBACKINFO
    typedef ::v8::FunctionCallbackInfo<::v8::Value> Args;

    std::string logArgs2String(const Args &args)
    {
        std::string message;
        for (int i = 0; i < args.Length(); i++) {
            ::v8::HandleScope scope(args.GetIsolate());
            ::v8::String::Utf8Value str(args[i]);
            message += *str;
        }
        return message;
    }
    void log(const Args &args)
    {
        LOG(info) << logArgs2String(args);
    }
    void error(const Args &args)
    {
        LOG(error) << logArgs2String(args);
    }
#else
    typedef ::v8::Arguments Args;

    std::string logArgs2String(const Args &args)
    {
        std::string message;
        for (int i = 0; i < args.Length(); i++) {
            ::v8::HandleScope scope;
            ::v8::String::Utf8Value str(args[i]);
            message += *str;
        }
        return message;
    }
    ::v8::Handle<::v8::Value> log(const Args &args)
    {
        LOG(info) << logArgs2String(args);
        return v8::Handle<v8::Value>();
    }
    ::v8::Handle<::v8::Value> error(const Args &args)
    {
        LOG(error) << logArgs2String(args);
        return v8::Handle<v8::Value>();
    }
#endif
}

namespace {
#ifdef HAVE_V8_WITH_MOST_CONSTRUCTORS_ISOLATE
    v8::Local<v8::String> newUtf8String(const char *data)
    {
        return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), data);
    }
    v8::Local<v8::FunctionTemplate> newFunctionTemplate(v8::FunctionCallback callback = NULL)
    {
        return v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), callback);
    }
#else
    v8::Local<v8::String> newUtf8String(const char *data)
    {
        return v8::String::New(data);
    }
    v8::Local<v8::FunctionTemplate> newFunctionTemplate(v8::FunctionCallback callback = NULL)
    {
        return v8::FunctionTemplate::New(callback);
    }
#endif
}

JsVm::JsVm(const std::string &code)
    : m_isolate(v8::Isolate::GetCurrent())
    , m_locker(m_isolate)
    , m_global(v8::ObjectTemplate::New())
{
    v8::Handle<v8::ObjectTemplate> console = v8::ObjectTemplate::New();
    m_global->Set(newUtf8String("console"), console);

    console->Set(newUtf8String("log"),
                 newFunctionTemplate(&Js::log));
    console->Set(newUtf8String("error"),
                 newFunctionTemplate(&Js::error));

    /**
     * We can't do this inside initialization list, since we are modifying
     * "m_global", and during ths gc can update references to it, since we are
     * adding _properties_ to it.
     *
     * And also to avoid Context::Scope for every call(), just enter context
     * here, since this module already provides "box" for executing
     * user-specific code in current thread.
     */
    m_context = v8::Context::New(NULL, m_global);
    m_context->Enter();

    m_source = newUtf8String(code.c_str());
}
JsVm::~JsVm()
{
    m_context->Exit();
}

bool JsVm::init()
{
    v8::Handle<v8::Script> script = v8::Script::Compile(m_source);
    if (!*script) {
        fillTryCatch();
        return false;
    }

    v8::Handle<v8::Value> sourceResult = script->Run();
    if (sourceResult.IsEmpty()) {
        fillTryCatch();
        return false;
    }

    m_function = v8::Handle<v8::Function>::Cast(sourceResult);
    return true;
}

void JsVm::call(const Db::Interface::Key &key, const Db::Interface::Value &value)
{
    v8::Local<v8::Value> args[] = {
        newUtf8String(key.c_str()),
        newUtf8String(value.c_str())
    };

    m_function->Call(m_context->Global(), 2, args);
}

void JsVm::fillTryCatch()
{
    v8::Handle<v8::Value> exception = m_trycatch.Exception();
    v8::String::AsciiValue exceptionMessage(exception);
    LOG(error) << *exceptionMessage;
}
<|endoftext|>


<commit_before>// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/
//
// File:      QtxDblSpinBox.cxx
// Author:    Sergey TELKOV

#include "QtxDblSpinBox.h"

#include <qlineedit.h>
#include <qvalidator.h>
#include <qapplication.h>

/*
	Class: QtxDblSpinBox::Validator [internal]
	Descr: Validator for QtxDblSpinBox (getted from Trolltech Qt - SpinBoxValidator)
*/

class QtxDblSpinBox::Validator : public QDoubleValidator
{
public:
    Validator( QtxDblSpinBox* sb, const char* name )
	: QDoubleValidator( sb, name ), spinBox( sb ) {}

    virtual State validate( QString& str, int& pos ) const;

private:
    QtxDblSpinBox* spinBox;
};

QValidator::State QtxDblSpinBox::Validator::validate( QString& str, int& pos ) const
{
  QString pref = spinBox->prefix();
  QString suff = spinBox->suffix();
  uint overhead = pref.length() + suff.length();
  State state = Invalid;

  if ( overhead == 0 )
	  state = QDoubleValidator::validate( str, pos );
  else
	{
		if ( str.length() >= overhead && str.startsWith( pref ) &&
         str.right( suff.length() ) == suff )
		{
			QString core = str.mid( pref.length(), str.length() - overhead );
			int corePos = pos - pref.length();
			state = QDoubleValidator::validate( core, corePos );
			pos = corePos + pref.length();
			str.replace( pref.length(), str.length() - overhead, core );
		}
		else
		{
			state = QDoubleValidator::validate( str, pos );
			if ( state == Invalid )
			{
				QString special = spinBox->specialValueText().stripWhiteSpace();
				QString candidate = str.stripWhiteSpace();
				if ( special.startsWith( candidate ) )
				{
					if ( candidate.length() == special.length() )
						state = Acceptable;
					else
						state = Intermediate;
				}
			}
		}
  }
  return state;
}

/*
	Class: QtxDblSpinBox
	Descr: Spin box for real numbers.
*/

QtxDblSpinBox::QtxDblSpinBox( QWidget* parent, const char* name )
: QSpinBox( parent, name ),
myCleared( false ),
myBlocked( false ),
myPrecision( 0 )
{
  myMin = QRangeControl::minValue();
  myMax = QRangeControl::maxValue();
  myStep = QRangeControl::lineStep();
	myValue = myMin;
  setValidator( new Validator( this, "double_spinbox_validator" ) );
  rangeChange();
  updateDisplay();

  connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
}

QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name )
: QSpinBox( parent, name ),
myMin( min ),
myMax( max ),
myStep( step ),
myCleared( false ),
myBlocked( false ),
myPrecision( 0 )
{
	myValue = myMin;
  setValidator( new Validator( this, "double_spinbox_validator" ) );
  rangeChange();
  updateDisplay();

  connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
}

QtxDblSpinBox::~QtxDblSpinBox()
{
}

double QtxDblSpinBox::minValue() const
{
  return myMin;
}

double QtxDblSpinBox::maxValue() const
{
  return myMax;
}

void QtxDblSpinBox::setMinValue( int min )
{
	setMinValue( (double)min );
}

void QtxDblSpinBox::setMinValue( double min )
{
  if ( myMin != min )
  {
    myMin = min;
    rangeChange();
  }
}

void QtxDblSpinBox::setMaxValue( int max )
{
	setMaxValue( (double)max );
}

void QtxDblSpinBox::setMaxValue( double max )
{
  if ( myMax != max )
  {
    myMax = max;
    rangeChange();
  }
}

void QtxDblSpinBox::setRange( int min, int max )
{
	setRange( (double)min, (double)max );
}

void QtxDblSpinBox::setRange( double min, double max )
{
  if ( myMin != min || myMax != max )
  {
    myMin = min;
    myMax = max;
    rangeChange();
  }
}

double QtxDblSpinBox::lineStep() const
{
  return myStep;
}

void QtxDblSpinBox::setLineStep( int step )
{
  setLineStep( (double)step );
}

void QtxDblSpinBox::setLineStep( double step )
{
  myStep = step;
}

double QtxDblSpinBox::value() const
{
  QSpinBox::value();

  return myValue;
}

void QtxDblSpinBox::setValue( int val )
{
	setValue( (double)val );
}

void QtxDblSpinBox::setValue( double val )
{
	myCleared = false;
  double prevVal = myValue;
  myValue = bound( val );
  if ( prevVal != myValue )
    valueChange();
}

void QtxDblSpinBox::stepUp()
{
	interpretText();
	if ( wrapping() && myValue + myStep > myMax )
		setValue( myMin );
	else
		setValue( myValue + myStep );
}

void QtxDblSpinBox::stepDown()
{
	interpretText();
	if ( wrapping() && myValue - myStep < myMin )
		setValue( myMax );
	else
		setValue( myValue - myStep );
}

int QtxDblSpinBox::precision() const
{
	return myPrecision;
}

void QtxDblSpinBox::setPrecision( const int prec )
{
	int newPrec = QMAX( prec, 0 );
	int oldPrec = QMAX( myPrecision, 0 );
	myPrecision = prec;
	if ( newPrec != oldPrec )
		updateDisplay();
}

bool QtxDblSpinBox::isCleared() const
{
	return myCleared;
}

void QtxDblSpinBox::setCleared( const bool on )
{
	if ( myCleared == on )
		return;

	myCleared = on;
	updateDisplay();
}

void QtxDblSpinBox::selectAll()
{
#if QT_VER >= 3
	QSpinBox::selectAll();
#else
  editor()->selectAll();
#endif
}

bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e )
{
  if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() )
    return QSpinBox::eventFilter( o, e );

  if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide )
    return false;

  if ( e->type() == QEvent::KeyPress &&
	  ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) )
  {
    QApplication::sendEvent( this, e );
    return true;
  }

  return QSpinBox::eventFilter( o, e );
}

void QtxDblSpinBox::updateDisplay()
{
  if ( myBlocked )
    return;

  bool upd = editor()->isUpdatesEnabled();
  editor()->setUpdatesEnabled( false );

  bool isBlock = myBlocked;
  myBlocked = true;

  QString txt = currentValueText();

  if ( myValue >= myMax )
    QSpinBox::setValue( QSpinBox::maxValue() );
  else if ( myValue <= myMin )
    QSpinBox::setValue( QSpinBox::minValue() );
  else
    QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 );

  QSpinBox::updateDisplay();

  editor()->setUpdatesEnabled( upd );

  editor()->setText( myCleared ? QString::null : txt );
  if ( !myCleared && editor()->hasFocus() )
  {
    if ( editor()->text() == specialValueText() )
      editor()->selectAll();
    else
      editor()->setSelection( prefix().length(), editor()->text().length() - prefix().length() - suffix().length() );
  }

  myBlocked = isBlock;
}

void QtxDblSpinBox::interpretText()
{
  myCleared = false;

  bool ok = true;
  bool done = false;
  double newVal = 0;
  if ( !specialValueText().isEmpty() )
  {
	  QString s = QString( text() ).stripWhiteSpace();
	  QString t = QString( specialValueText() ).stripWhiteSpace();
	  if ( s == t )
    {
      newVal = minValue();
	    done = true;
    }
  }
  if ( !done )
	  newVal = mapTextToDoubleValue( &ok );
  if ( ok )
	  setValue( newVal );
  updateDisplay();
}

void QtxDblSpinBox::valueChange()
{
  updateDisplay();
  emit valueChanged( myValue );
  emit valueChanged( currentValueText() );
}

void QtxDblSpinBox::rangeChange()
{
  double min = QMIN( myMin, myMax );
  double max = QMAX( myMin, myMax );
  myMin = min;
  myMax = max;
  if ( validator()->inherits( "QDoubleValidator" ) )
    ((QDoubleValidator*)validator())->setRange( myMin, myMax );

	if ( myMin == myMax )
		QSpinBox::setRange( 0, 0 );
	else
		QSpinBox::setRange( 0, 2 );

  setValue( myValue );
  updateDisplay();
}

QString QtxDblSpinBox::currentValueText()
{
  QString s;
  if ( (myValue == minValue()) && !specialValueText().isEmpty() )
	  s = specialValueText();
  else
	{
	  s = prefix();
		s.append( mapValueToText( myValue ) );
		s.append( suffix() );
	}
  return s;
}

QString QtxDblSpinBox::mapValueToText( double v )
{
	QString s;
  s.setNum( v, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
  return removeTrailingZeroes( s );
}

QString QtxDblSpinBox::mapValueToText( int )
{
  QString s;
  s.setNum( myValue, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
  return removeTrailingZeroes( s );
}

double QtxDblSpinBox::mapTextToDoubleValue( bool* ok )
{
  QString s = text();
  double newVal = s.toDouble( ok );
  if ( !(*ok) && !( !prefix() && !suffix() ) )
  {
	  s = cleanText();
	  newVal = s.toDouble( ok );
  }
  return newVal;
}

double QtxDblSpinBox::bound( double val )
{
  double newVal = val;
  if ( newVal > myMax )
    newVal = myMax;
  if ( newVal < myMin )
    newVal = myMin;
  return newVal;
}

void QtxDblSpinBox::leaveEvent( QEvent* e )
{
	if ( !myCleared )
		QSpinBox::leaveEvent( e );
}

void QtxDblSpinBox::wheelEvent( QWheelEvent* e )
{
  if ( !isEnabled() )
    return;

  QSpinBox::wheelEvent( e );
  updateDisplay();
}

void QtxDblSpinBox::onTextChanged( const QString& str )
{
  if ( !myBlocked )
    myCleared = false;
}

QString QtxDblSpinBox::removeTrailingZeroes( const QString& src ) const
{
  QString delim( "." );

  int idx = src.findRev( delim );
  if ( idx == -1 )
    return src;

  QString iPart = src.left( idx );
  QString fPart = src.mid( idx + 1 );

  while ( !fPart.isEmpty() && fPart.at( fPart.length() - 1 ) == '0' )
    fPart.remove( fPart.length() - 1, 1 );

  QString res = iPart;
  if ( !fPart.isEmpty() )
    res += delim + fPart;

  return res;
}
<commit_msg>Added checking of the validator pointer.<commit_after>// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/
//
// File:      QtxDblSpinBox.cxx
// Author:    Sergey TELKOV

#include "QtxDblSpinBox.h"

#include <qlineedit.h>
#include <qvalidator.h>
#include <qapplication.h>

/*
	Class: QtxDblSpinBox::Validator [internal]
	Descr: Validator for QtxDblSpinBox (getted from Trolltech Qt - SpinBoxValidator)
*/

class QtxDblSpinBox::Validator : public QDoubleValidator
{
public:
    Validator( QtxDblSpinBox* sb, const char* name )
	: QDoubleValidator( sb, name ), spinBox( sb ) {}

    virtual State validate( QString& str, int& pos ) const;

private:
    QtxDblSpinBox* spinBox;
};

QValidator::State QtxDblSpinBox::Validator::validate( QString& str, int& pos ) const
{
  QString pref = spinBox->prefix();
  QString suff = spinBox->suffix();
  uint overhead = pref.length() + suff.length();
  State state = Invalid;

  if ( overhead == 0 )
	  state = QDoubleValidator::validate( str, pos );
  else
	{
		if ( str.length() >= overhead && str.startsWith( pref ) &&
         str.right( suff.length() ) == suff )
		{
			QString core = str.mid( pref.length(), str.length() - overhead );
			int corePos = pos - pref.length();
			state = QDoubleValidator::validate( core, corePos );
			pos = corePos + pref.length();
			str.replace( pref.length(), str.length() - overhead, core );
		}
		else
		{
			state = QDoubleValidator::validate( str, pos );
			if ( state == Invalid )
			{
				QString special = spinBox->specialValueText().stripWhiteSpace();
				QString candidate = str.stripWhiteSpace();
				if ( special.startsWith( candidate ) )
				{
					if ( candidate.length() == special.length() )
						state = Acceptable;
					else
						state = Intermediate;
				}
			}
		}
  }
  return state;
}

/*
	Class: QtxDblSpinBox
	Descr: Spin box for real numbers.
*/

QtxDblSpinBox::QtxDblSpinBox( QWidget* parent, const char* name )
: QSpinBox( parent, name ),
myCleared( false ),
myBlocked( false ),
myPrecision( 0 )
{
  myMin = QRangeControl::minValue();
  myMax = QRangeControl::maxValue();
  myStep = QRangeControl::lineStep();
	myValue = myMin;
  setValidator( new Validator( this, "double_spinbox_validator" ) );
  rangeChange();
  updateDisplay();

  connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
}

QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name )
: QSpinBox( parent, name ),
myMin( min ),
myMax( max ),
myStep( step ),
myCleared( false ),
myBlocked( false ),
myPrecision( 0 )
{
	myValue = myMin;
  setValidator( new Validator( this, "double_spinbox_validator" ) );
  rangeChange();
  updateDisplay();

  connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
}

QtxDblSpinBox::~QtxDblSpinBox()
{
}

double QtxDblSpinBox::minValue() const
{
  return myMin;
}

double QtxDblSpinBox::maxValue() const
{
  return myMax;
}

void QtxDblSpinBox::setMinValue( int min )
{
	setMinValue( (double)min );
}

void QtxDblSpinBox::setMinValue( double min )
{
  if ( myMin != min )
  {
    myMin = min;
    rangeChange();
  }
}

void QtxDblSpinBox::setMaxValue( int max )
{
	setMaxValue( (double)max );
}

void QtxDblSpinBox::setMaxValue( double max )
{
  if ( myMax != max )
  {
    myMax = max;
    rangeChange();
  }
}

void QtxDblSpinBox::setRange( int min, int max )
{
	setRange( (double)min, (double)max );
}

void QtxDblSpinBox::setRange( double min, double max )
{
  if ( myMin != min || myMax != max )
  {
    myMin = min;
    myMax = max;
    rangeChange();
  }
}

double QtxDblSpinBox::lineStep() const
{
  return myStep;
}

void QtxDblSpinBox::setLineStep( int step )
{
  setLineStep( (double)step );
}

void QtxDblSpinBox::setLineStep( double step )
{
  myStep = step;
}

double QtxDblSpinBox::value() const
{
  QSpinBox::value();

  return myValue;
}

void QtxDblSpinBox::setValue( int val )
{
	setValue( (double)val );
}

void QtxDblSpinBox::setValue( double val )
{
	myCleared = false;
  double prevVal = myValue;
  myValue = bound( val );
  if ( prevVal != myValue )
    valueChange();
}

void QtxDblSpinBox::stepUp()
{
	interpretText();
	if ( wrapping() && myValue + myStep > myMax )
		setValue( myMin );
	else
		setValue( myValue + myStep );
}

void QtxDblSpinBox::stepDown()
{
	interpretText();
	if ( wrapping() && myValue - myStep < myMin )
		setValue( myMax );
	else
		setValue( myValue - myStep );
}

int QtxDblSpinBox::precision() const
{
	return myPrecision;
}

void QtxDblSpinBox::setPrecision( const int prec )
{
	int newPrec = QMAX( prec, 0 );
	int oldPrec = QMAX( myPrecision, 0 );
	myPrecision = prec;
	if ( newPrec != oldPrec )
		updateDisplay();
}

bool QtxDblSpinBox::isCleared() const
{
	return myCleared;
}

void QtxDblSpinBox::setCleared( const bool on )
{
	if ( myCleared == on )
		return;

	myCleared = on;
	updateDisplay();
}

void QtxDblSpinBox::selectAll()
{
#if QT_VER >= 3
	QSpinBox::selectAll();
#else
  editor()->selectAll();
#endif
}

bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e )
{
  if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() )
    return QSpinBox::eventFilter( o, e );

  if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide )
    return false;

  if ( e->type() == QEvent::KeyPress &&
	  ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) )
  {
    QApplication::sendEvent( this, e );
    return true;
  }

  return QSpinBox::eventFilter( o, e );
}

void QtxDblSpinBox::updateDisplay()
{
  if ( myBlocked )
    return;

  bool upd = editor()->isUpdatesEnabled();
  editor()->setUpdatesEnabled( false );

  bool isBlock = myBlocked;
  myBlocked = true;

  QString txt = currentValueText();

  if ( myValue >= myMax )
    QSpinBox::setValue( QSpinBox::maxValue() );
  else if ( myValue <= myMin )
    QSpinBox::setValue( QSpinBox::minValue() );
  else
    QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 );

  QSpinBox::updateDisplay();

  editor()->setUpdatesEnabled( upd );

  editor()->setText( myCleared ? QString::null : txt );
  if ( !myCleared && editor()->hasFocus() )
  {
    if ( editor()->text() == specialValueText() )
      editor()->selectAll();
    else
      editor()->setSelection( prefix().length(), editor()->text().length() - prefix().length() - suffix().length() );
  }

  myBlocked = isBlock;
}

void QtxDblSpinBox::interpretText()
{
  myCleared = false;

  bool ok = true;
  bool done = false;
  double newVal = 0;
  if ( !specialValueText().isEmpty() )
  {
	  QString s = QString( text() ).stripWhiteSpace();
	  QString t = QString( specialValueText() ).stripWhiteSpace();
	  if ( s == t )
    {
      newVal = minValue();
	    done = true;
    }
  }
  if ( !done )
	  newVal = mapTextToDoubleValue( &ok );
  if ( ok )
	  setValue( newVal );
  updateDisplay();
}

void QtxDblSpinBox::valueChange()
{
  updateDisplay();
  emit valueChanged( myValue );
  emit valueChanged( currentValueText() );
}

void QtxDblSpinBox::rangeChange()
{
  double min = QMIN( myMin, myMax );
  double max = QMAX( myMin, myMax );
  myMin = min;
  myMax = max;
  QDoubleValidator* v = ::qt_cast<QDoubleValidator*>( validator() );
  if ( v )
    v->setRange( myMin, myMax );

	if ( myMin == myMax )
		QSpinBox::setRange( 0, 0 );
	else
		QSpinBox::setRange( 0, 2 );

  setValue( myValue );
  updateDisplay();
}

QString QtxDblSpinBox::currentValueText()
{
  QString s;
  if ( (myValue == minValue()) && !specialValueText().isEmpty() )
	  s = specialValueText();
  else
	{
	  s = prefix();
		s.append( mapValueToText( myValue ) );
		s.append( suffix() );
	}
  return s;
}

QString QtxDblSpinBox::mapValueToText( double v )
{
	QString s;
  s.setNum( v, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
  return removeTrailingZeroes( s );
}

QString QtxDblSpinBox::mapValueToText( int )
{
  QString s;
  s.setNum( myValue, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
  return removeTrailingZeroes( s );
}

double QtxDblSpinBox::mapTextToDoubleValue( bool* ok )
{
  QString s = text();
  double newVal = s.toDouble( ok );
  if ( !(*ok) && !( !prefix() && !suffix() ) )
  {
	  s = cleanText();
	  newVal = s.toDouble( ok );
  }
  return newVal;
}

double QtxDblSpinBox::bound( double val )
{
  double newVal = val;
  if ( newVal > myMax )
    newVal = myMax;
  if ( newVal < myMin )
    newVal = myMin;
  return newVal;
}

void QtxDblSpinBox::leaveEvent( QEvent* e )
{
	if ( !myCleared )
		QSpinBox::leaveEvent( e );
}

void QtxDblSpinBox::wheelEvent( QWheelEvent* e )
{
  if ( !isEnabled() )
    return;

  QSpinBox::wheelEvent( e );
  updateDisplay();
}

void QtxDblSpinBox::onTextChanged( const QString& str )
{
  if ( !myBlocked )
    myCleared = false;
}

QString QtxDblSpinBox::removeTrailingZeroes( const QString& src ) const
{
  QString delim( "." );

  int idx = src.findRev( delim );
  if ( idx == -1 )
    return src;

  QString iPart = src.left( idx );
  QString fPart = src.mid( idx + 1 );

  while ( !fPart.isEmpty() && fPart.at( fPart.length() - 1 ) == '0' )
    fPart.remove( fPart.length() - 1, 1 );

  QString res = iPart;
  if ( !fPart.isEmpty() )
    res += delim + fPart;

  return res;
}
<|endoftext|>