<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDBus module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdbusconnectioninterface.h"

#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtCore/QDebug>

#include <qdbus_symbols_p.h>          // for the DBUS_* constants

QT_BEGIN_NAMESPACE

/*
 * Implementation of interface class QDBusConnectionInterface
 */

/*!
    \class QDBusConnectionInterface
    \inmodule QtDBus
    \since 4.2

    \brief The QDBusConnectionInterface class provides access to the D-Bus bus daemon service.

    The D-Bus bus server daemon provides one special interface \c
    org.freedesktop.DBus that allows clients to access certain
    properties of the bus, such as the current list of clients
    connected. The QDBusConnectionInterface class provides access to that
    interface.

    The most common uses of this class are to register and unregister
    service names on the bus using the registerService() and
    unregisterService() functions, query about existing names using
    the isServiceRegistered(), registeredServiceNames() and
    serviceOwner() functions, and to receive notification that a
    client has registered or de-registered through the
    serviceRegistered(), serviceUnregistered() and serviceOwnerChanged()
    signals.
*/

/*!
    \enum QDBusConnectionInterface::ServiceQueueOptions

    Flags for determining how a service registration should behave, in
    case the service name is already registered.

    \value DontQueueService     If an application requests a name that
                                is already owned, no queueing will be
                                performed. The registeredService()
                                call will simply fail.
                                This is the default.

    \value QueueService         Attempts to register the requested
                                service, but do not try to replace it
                                if another application already has it
                                registered. Instead, simply put this
                                application in queue, until it is
                                given up. The serviceRegistered()
                                signal will be emitted when that
                                happens.

    \value ReplaceExistingService If another application already has
                                the service name registered, attempt
                                to replace it.

    \sa ServiceReplacementOptions
*/

/*!
    \enum QDBusConnectionInterface::ServiceReplacementOptions

    Flags for determining if the D-Bus server should allow another
    application to replace a name that this application has registered
    with the ReplaceExistingService option.

    The possible values are:

    \value DontAllowReplacement Do not allow another application to
                                replace us. The service must be
                                explicitly unregistered with
                                unregisterService() for another
                                application to acquire it.
                                This is the default.

    \value AllowReplacement     Allow other applications to replace us
                                with the ReplaceExistingService option
                                to registerService() without
                                intervention. If that happens, the
                                serviceUnregistered() signal will be
                                emitted.

    \sa ServiceQueueOptions
*/

/*!
    \enum QDBusConnectionInterface::RegisterServiceReply

    The possible return values from registerService():

    \value ServiceNotRegistered The call failed and the service name was not registered.
    \value ServiceRegistered    The caller is now the owner of the service name.
    \value ServiceQueued        The caller specified the QueueService flag and the
                                service was already registered, so we are in queue.

    The serviceRegistered() signal will be emitted when the service is
    acquired by this application.
*/

/*!
    \internal
*/
const char *QDBusConnectionInterface::staticInterfaceName()
{ return "org.freedesktop.DBus"; }

/*!
    \internal
*/
QDBusConnectionInterface::QDBusConnectionInterface(const QDBusConnection &connection,
                                                   QObject *parent)
    : QDBusAbstractInterface(QLatin1String(DBUS_SERVICE_DBUS),
                             QLatin1String(DBUS_PATH_DBUS),
                             DBUS_INTERFACE_DBUS, connection, parent)
{
    connect(this, SIGNAL(NameAcquired(QString)), this, SIGNAL(serviceRegistered(QString)));
    connect(this, SIGNAL(NameLost(QString)), this, SIGNAL(serviceUnregistered(QString)));
    connect(this, SIGNAL(NameOwnerChanged(QString,QString,QString)),
            this, SIGNAL(serviceOwnerChanged(QString,QString,QString)));
}

/*!
    \internal
*/
QDBusConnectionInterface::~QDBusConnectionInterface()
{
}

/*!
    Returns the unique connection name of the primary owner of the
    name \a name. If the requested name doesn't have an owner, returns
    a \c org.freedesktop.DBus.Error.NameHasNoOwner error.
*/
QDBusReply<QString> QDBusConnectionInterface::serviceOwner(const QString &name) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("GetNameOwner"), QList<QVariant>() << name);
}

/*!
  \property QDBusConnectionInterface::registeredServiceNames
  \brief holds the registered service names

  Lists all names currently registered on the bus.
*/
QDBusReply<QStringList> QDBusConnectionInterface::registeredServiceNames() const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("ListNames"));
}

/*!
    Returns true if the service name \a serviceName has is currently
    registered.
*/
QDBusReply<bool> QDBusConnectionInterface::isServiceRegistered(const QString &serviceName) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("NameHasOwner"),
                             QList<QVariant>() << serviceName);
}

/*!
    Returns the Unix Process ID (PID) for the process currently
    holding the bus service \a serviceName.
*/
QDBusReply<uint> QDBusConnectionInterface::servicePid(const QString &serviceName) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("GetConnectionUnixProcessID"),
                             QList<QVariant>() << serviceName);
}

/*!
    Returns the Unix User ID (UID) for the process currently holding
    the bus service \a serviceName.
*/
QDBusReply<uint> QDBusConnectionInterface::serviceUid(const QString &serviceName) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("GetConnectionUnixUser"),
                             QList<QVariant>() << serviceName);
}

/*!
    Requests that the bus start the service given by the name \a name.
*/
QDBusReply<void> QDBusConnectionInterface::startService(const QString &name)
{
    return call(QLatin1String("StartServiceByName"), name, uint(0));
}

/*!
    Requests to register the service name \a serviceName on the
    bus. The \a qoption flag specifies how the D-Bus server should behave
    if \a serviceName is already registered. The \a roption flag
    specifies if the server should allow another application to
    replace our registered name.

    If the service registration succeeds, the serviceRegistered()
    signal will be emitted. If we are placed in queue, the signal will
    be emitted when we obtain the name. If \a roption is
    AllowReplacement, the serviceUnregistered() signal will be emitted
    if another application replaces this one.

    \sa unregisterService()
*/
QDBusReply<QDBusConnectionInterface::RegisterServiceReply>
QDBusConnectionInterface::registerService(const QString &serviceName,
                                          ServiceQueueOptions qoption,
                                          ServiceReplacementOptions roption)
{
    // reconstruct the low-level flags
    uint flags = 0;
    switch (qoption) {
    case DontQueueService:
        flags = DBUS_NAME_FLAG_DO_NOT_QUEUE;
        break;
    case QueueService:
        flags = 0;
        break;
    case ReplaceExistingService:
        flags = DBUS_NAME_FLAG_DO_NOT_QUEUE | DBUS_NAME_FLAG_REPLACE_EXISTING;
        break;
    }

    switch (roption) {
    case DontAllowReplacement:
        break;
    case AllowReplacement:
        flags |= DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
        break;
    }

    QDBusMessage reply = call(QLatin1String("RequestName"), serviceName, flags);
//    qDebug() << "QDBusConnectionInterface::registerService" << serviceName << "Reply:" << reply;

    // convert the low-level flags to something that we can use
    if (reply.type() == QDBusMessage::ReplyMessage) {
        uint code = 0;

        switch (reply.arguments().at(0).toUInt()) {
        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
        case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
            code = uint(ServiceRegistered);
            break;

        case DBUS_REQUEST_NAME_REPLY_EXISTS:
            code = uint(ServiceNotRegistered);
            break;

        case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
            code = uint(ServiceQueued);
            break;
        }

        reply.setArguments(QVariantList() << code);
    }

    return reply;
}

/*!
    Releases the claim on the bus service name \a serviceName, that
    had been previously registered with registerService(). If this
    application had ownership of the name, it will be released for
    other applications to claim. If it only had the name queued, it
    gives up its position in the queue.
*/
QDBusReply<bool>
QDBusConnectionInterface::unregisterService(const QString &serviceName)
{
    QDBusMessage reply = call(QLatin1String("ReleaseName"), serviceName);
    if (reply.type() == QDBusMessage::ReplyMessage) {
        bool success = reply.arguments().at(0).toUInt() == DBUS_RELEASE_NAME_REPLY_RELEASED;
        reply.setArguments(QVariantList() << success);
    }
    return reply;
}

/*!
    \internal
*/
void QDBusConnectionInterface::connectNotify(const char *signalName)
{
    // translate the signal names to what we really want
    // this avoids setting hooks for signals that don't exist on the bus
    if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
        QDBusAbstractInterface::connectNotify(SIGNAL(NameAcquired(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
        QDBusAbstractInterface::connectNotify(SIGNAL(NameLost(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0)
        QDBusAbstractInterface::connectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
}

/*!
    \internal
*/
void QDBusConnectionInterface::disconnectNotify(const char *signalName)
{
    // translate the signal names to what we really want
    // this avoids setting hooks for signals that don't exist on the bus
    if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
        QDBusAbstractInterface::disconnectNotify(SIGNAL(NameAcquired(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
        QDBusAbstractInterface::disconnectNotify(SIGNAL(NameLost(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0)
        QDBusAbstractInterface::disconnectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
}

// signals
/*!
    \fn QDBusConnectionInterface::serviceRegistered(const QString &serviceName)

    This signal is emitted by the D-Bus server when the bus service
    name (unique connection name or well-known service name) given by
    \a serviceName is acquired by this application.

    Acquisition happens after this application has requested a name using
    registerService().
*/

/*!
    \fn QDBusConnectionInterface::serviceUnregistered(const QString &serviceName)

    This signal is emitted by the D-Bus server when this application
    loses ownership of the bus service name given by \a serviceName.
*/

/*!
    \fn QDBusConnectionInterface::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)

    This signal is emitted by the D-Bus server whenever a service
    ownership change happens in the bus, including apparition and
    disparition of names.

    This signal means the application \a oldOwner lost ownership of
    bus name \a name to application \a newOwner. If \a oldOwner is an
    empty string, it means the name \a name has just been created; if
    \a newOwner is empty, the name \a name has no current owner and is
    no longer available.
*/

/*!
  \fn void QDBusConnectionInterface::callWithCallbackFailed(const QDBusError &error, const QDBusMessage &call)

  This signal is emitted when there is an error during a
  QDBusConnection::callWithCallback(). \a error specifies the error.
  \a call is the message that couldn't be delivered.

  \sa QDBusConnection::callWithCallback()
 */

QT_END_NAMESPACE
<commit_msg>Add a warning to user's connecting to serviceOwnerChanged directly<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDBus module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdbusconnectioninterface.h"

#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtCore/QDebug>

#include <qdbus_symbols_p.h>          // for the DBUS_* constants

QT_BEGIN_NAMESPACE

/*
 * Implementation of interface class QDBusConnectionInterface
 */

/*!
    \class QDBusConnectionInterface
    \inmodule QtDBus
    \since 4.2

    \brief The QDBusConnectionInterface class provides access to the D-Bus bus daemon service.

    The D-Bus bus server daemon provides one special interface \c
    org.freedesktop.DBus that allows clients to access certain
    properties of the bus, such as the current list of clients
    connected. The QDBusConnectionInterface class provides access to that
    interface.

    The most common uses of this class are to register and unregister
    service names on the bus using the registerService() and
    unregisterService() functions, query about existing names using
    the isServiceRegistered(), registeredServiceNames() and
    serviceOwner() functions, and to receive notification that a
    client has registered or de-registered through the
    serviceRegistered(), serviceUnregistered() and serviceOwnerChanged()
    signals.
*/

/*!
    \enum QDBusConnectionInterface::ServiceQueueOptions

    Flags for determining how a service registration should behave, in
    case the service name is already registered.

    \value DontQueueService     If an application requests a name that
                                is already owned, no queueing will be
                                performed. The registeredService()
                                call will simply fail.
                                This is the default.

    \value QueueService         Attempts to register the requested
                                service, but do not try to replace it
                                if another application already has it
                                registered. Instead, simply put this
                                application in queue, until it is
                                given up. The serviceRegistered()
                                signal will be emitted when that
                                happens.

    \value ReplaceExistingService If another application already has
                                the service name registered, attempt
                                to replace it.

    \sa ServiceReplacementOptions
*/

/*!
    \enum QDBusConnectionInterface::ServiceReplacementOptions

    Flags for determining if the D-Bus server should allow another
    application to replace a name that this application has registered
    with the ReplaceExistingService option.

    The possible values are:

    \value DontAllowReplacement Do not allow another application to
                                replace us. The service must be
                                explicitly unregistered with
                                unregisterService() for another
                                application to acquire it.
                                This is the default.

    \value AllowReplacement     Allow other applications to replace us
                                with the ReplaceExistingService option
                                to registerService() without
                                intervention. If that happens, the
                                serviceUnregistered() signal will be
                                emitted.

    \sa ServiceQueueOptions
*/

/*!
    \enum QDBusConnectionInterface::RegisterServiceReply

    The possible return values from registerService():

    \value ServiceNotRegistered The call failed and the service name was not registered.
    \value ServiceRegistered    The caller is now the owner of the service name.
    \value ServiceQueued        The caller specified the QueueService flag and the
                                service was already registered, so we are in queue.

    The serviceRegistered() signal will be emitted when the service is
    acquired by this application.
*/

/*!
    \internal
*/
const char *QDBusConnectionInterface::staticInterfaceName()
{ return "org.freedesktop.DBus"; }

/*!
    \internal
*/
QDBusConnectionInterface::QDBusConnectionInterface(const QDBusConnection &connection,
                                                   QObject *parent)
    : QDBusAbstractInterface(QLatin1String(DBUS_SERVICE_DBUS),
                             QLatin1String(DBUS_PATH_DBUS),
                             DBUS_INTERFACE_DBUS, connection, parent)
{
    connect(this, SIGNAL(NameAcquired(QString)), this, SIGNAL(serviceRegistered(QString)));
    connect(this, SIGNAL(NameLost(QString)), this, SIGNAL(serviceUnregistered(QString)));
    connect(this, SIGNAL(NameOwnerChanged(QString,QString,QString)),
            this, SIGNAL(serviceOwnerChanged(QString,QString,QString)));
}

/*!
    \internal
*/
QDBusConnectionInterface::~QDBusConnectionInterface()
{
}

/*!
    Returns the unique connection name of the primary owner of the
    name \a name. If the requested name doesn't have an owner, returns
    a \c org.freedesktop.DBus.Error.NameHasNoOwner error.
*/
QDBusReply<QString> QDBusConnectionInterface::serviceOwner(const QString &name) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("GetNameOwner"), QList<QVariant>() << name);
}

/*!
  \property QDBusConnectionInterface::registeredServiceNames
  \brief holds the registered service names

  Lists all names currently registered on the bus.
*/
QDBusReply<QStringList> QDBusConnectionInterface::registeredServiceNames() const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("ListNames"));
}

/*!
    Returns true if the service name \a serviceName has is currently
    registered.
*/
QDBusReply<bool> QDBusConnectionInterface::isServiceRegistered(const QString &serviceName) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("NameHasOwner"),
                             QList<QVariant>() << serviceName);
}

/*!
    Returns the Unix Process ID (PID) for the process currently
    holding the bus service \a serviceName.
*/
QDBusReply<uint> QDBusConnectionInterface::servicePid(const QString &serviceName) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("GetConnectionUnixProcessID"),
                             QList<QVariant>() << serviceName);
}

/*!
    Returns the Unix User ID (UID) for the process currently holding
    the bus service \a serviceName.
*/
QDBusReply<uint> QDBusConnectionInterface::serviceUid(const QString &serviceName) const
{
    return internalConstCall(QDBus::AutoDetect, QLatin1String("GetConnectionUnixUser"),
                             QList<QVariant>() << serviceName);
}

/*!
    Requests that the bus start the service given by the name \a name.
*/
QDBusReply<void> QDBusConnectionInterface::startService(const QString &name)
{
    return call(QLatin1String("StartServiceByName"), name, uint(0));
}

/*!
    Requests to register the service name \a serviceName on the
    bus. The \a qoption flag specifies how the D-Bus server should behave
    if \a serviceName is already registered. The \a roption flag
    specifies if the server should allow another application to
    replace our registered name.

    If the service registration succeeds, the serviceRegistered()
    signal will be emitted. If we are placed in queue, the signal will
    be emitted when we obtain the name. If \a roption is
    AllowReplacement, the serviceUnregistered() signal will be emitted
    if another application replaces this one.

    \sa unregisterService()
*/
QDBusReply<QDBusConnectionInterface::RegisterServiceReply>
QDBusConnectionInterface::registerService(const QString &serviceName,
                                          ServiceQueueOptions qoption,
                                          ServiceReplacementOptions roption)
{
    // reconstruct the low-level flags
    uint flags = 0;
    switch (qoption) {
    case DontQueueService:
        flags = DBUS_NAME_FLAG_DO_NOT_QUEUE;
        break;
    case QueueService:
        flags = 0;
        break;
    case ReplaceExistingService:
        flags = DBUS_NAME_FLAG_DO_NOT_QUEUE | DBUS_NAME_FLAG_REPLACE_EXISTING;
        break;
    }

    switch (roption) {
    case DontAllowReplacement:
        break;
    case AllowReplacement:
        flags |= DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
        break;
    }

    QDBusMessage reply = call(QLatin1String("RequestName"), serviceName, flags);
//    qDebug() << "QDBusConnectionInterface::registerService" << serviceName << "Reply:" << reply;

    // convert the low-level flags to something that we can use
    if (reply.type() == QDBusMessage::ReplyMessage) {
        uint code = 0;

        switch (reply.arguments().at(0).toUInt()) {
        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
        case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
            code = uint(ServiceRegistered);
            break;

        case DBUS_REQUEST_NAME_REPLY_EXISTS:
            code = uint(ServiceNotRegistered);
            break;

        case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
            code = uint(ServiceQueued);
            break;
        }

        reply.setArguments(QVariantList() << code);
    }

    return reply;
}

/*!
    Releases the claim on the bus service name \a serviceName, that
    had been previously registered with registerService(). If this
    application had ownership of the name, it will be released for
    other applications to claim. If it only had the name queued, it
    gives up its position in the queue.
*/
QDBusReply<bool>
QDBusConnectionInterface::unregisterService(const QString &serviceName)
{
    QDBusMessage reply = call(QLatin1String("ReleaseName"), serviceName);
    if (reply.type() == QDBusMessage::ReplyMessage) {
        bool success = reply.arguments().at(0).toUInt() == DBUS_RELEASE_NAME_REPLY_RELEASED;
        reply.setArguments(QVariantList() << success);
    }
    return reply;
}

/*!
    \internal
*/
void QDBusConnectionInterface::connectNotify(const char *signalName)
{
    // translate the signal names to what we really want
    // this avoids setting hooks for signals that don't exist on the bus
    if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
        QDBusAbstractInterface::connectNotify(SIGNAL(NameAcquired(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
        QDBusAbstractInterface::connectNotify(SIGNAL(NameLost(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0) {
        static bool warningPrinted = false;
        if (!warningPrinted) {
            qWarning("Connecting to deprecated signal QDBusConnectionInterface::serviceOwnerChanged(QString,QString,QString)");
            warningPrinted = true;
        }
        QDBusAbstractInterface::connectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
    }
}

/*!
    \internal
*/
void QDBusConnectionInterface::disconnectNotify(const char *signalName)
{
    // translate the signal names to what we really want
    // this avoids setting hooks for signals that don't exist on the bus
    if (qstrcmp(signalName, SIGNAL(serviceRegistered(QString))) == 0)
        QDBusAbstractInterface::disconnectNotify(SIGNAL(NameAcquired(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceUnregistered(QString))) == 0)
        QDBusAbstractInterface::disconnectNotify(SIGNAL(NameLost(QString)));

    else if (qstrcmp(signalName, SIGNAL(serviceOwnerChanged(QString,QString,QString))) == 0)
        QDBusAbstractInterface::disconnectNotify(SIGNAL(NameOwnerChanged(QString,QString,QString)));
}

// signals
/*!
    \fn QDBusConnectionInterface::serviceRegistered(const QString &serviceName)

    This signal is emitted by the D-Bus server when the bus service
    name (unique connection name or well-known service name) given by
    \a serviceName is acquired by this application.

    Acquisition happens after this application has requested a name using
    registerService().
*/

/*!
    \fn QDBusConnectionInterface::serviceUnregistered(const QString &serviceName)

    This signal is emitted by the D-Bus server when this application
    loses ownership of the bus service name given by \a serviceName.
*/

/*!
    \fn QDBusConnectionInterface::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)

    This signal is emitted by the D-Bus server whenever a service
    ownership change happens in the bus, including apparition and
    disparition of names.

    This signal means the application \a oldOwner lost ownership of
    bus name \a name to application \a newOwner. If \a oldOwner is an
    empty string, it means the name \a name has just been created; if
    \a newOwner is empty, the name \a name has no current owner and is
    no longer available.
*/

/*!
  \fn void QDBusConnectionInterface::callWithCallbackFailed(const QDBusError &error, const QDBusMessage &call)

  This signal is emitted when there is an error during a
  QDBusConnection::callWithCallback(). \a error specifies the error.
  \a call is the message that couldn't be delivered.

  \sa QDBusConnection::callWithCallback()
 */

QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include "BattleStation.h"
#include <OgreNode.h>
#include "GestShip.h"
using namespace Ogre;

BattleStation::BattleStation(void) : ShipAbstract(ObjectRoot::SHIP_BATTLE_STATION)
{
    this->typeObject = ObjectRoot::SHIP_BATTLE_STATION;
    this->speed = 0.4;
    this->mRotFrames = 10000;
    this->destination = Ogre::Vector3(130,0,9000);
    mRotating = true;
    mRotFactor = 1;
    mRotProgress = 1;
    this->getNode()->setScale(Ogre::Vector3(0.1,0.1,0.1));
}

BattleStation::~BattleStation(void)
{

}

void BattleStation::updatePosition(void)
{
    Ogre::Vector3 direction = this->getNode()->getPosition()-this->destination;
    //commenté pke bouffeur de FPS = les particules ne meurent pas
    if(direction.squaredLength()<40000000)
    {

       // this->shootLaser();
    }

    //Se tourne vers nous plus ou moins (mRotFactor == vitesse à laquelle c fait et avant que le vsx change de destination => inversement proportionnel)
        if(mRotating)
        {
          mRotProgress += mRotFactor;
          if(mRotProgress>1)
          {
              this->destination = GestShip::getSingleton()->getAllShips().at(0)->getNode()->getPosition()+Ogre::Vector3(Utils::randRangeInt(-10000,10000),Utils::randRangeInt(-10000,10000),Utils::randRangeInt(-10000,10000));
              mRotating = false;
              mRotating = true;
              mRotFactor = 1.0f / mRotFrames;
              mOrientSrc = this->getNode()->getOrientation();
              Ogre::Quaternion quat =  (this->getNode()->getOrientation()* Vector3::UNIT_Z).getRotationTo(    this->destination-this->getNode()->getPosition());
              mOrientDest = quat * mOrientSrc;           // We want dest orientation, not a relative rotation (quat)
              mRotProgress = 0;
          }
          else
          {
              //rotation
              Quaternion delta = Quaternion::Slerp(mRotProgress, mOrientSrc, mOrientDest, true);
              this->getNode()->setOrientation(delta);
          }
        }
        //si on est encore loin on avance
        if(direction.squaredLength()>4000000)
        {
            this->setSpeed(speed);

        }else{
            this->setSpeed(0);
        }
             if (this->getSpeed() != 0)
            {
                this->moveRelative(0.0, 0.0, this->getSpeed());
            }
        //TODO:peut etre translaté tjs tout droit par rapport à lui meme et on corrige l'orientation du vsx = effet plus smoothy je pense
   /* }else
    {
        mRotating = true;
        mRotFactor = 1.0f / 10;
        mOrientSrc = this->getNode()->getOrientation();
        Ogre::Quaternion quat =  (this->getNode()->getOrientation()* Vector3::UNIT_X).getRotationTo( GestShip::getSingleton()->getAllShips().at(0)->getNode()->getPosition());
        mOrientDest = quat * mOrientSrc;           // We want dest orientation, not a relative rotation (quat)
        mRotProgress = 0;
        /*
        Ogre::Vector3 dir = Ogre::Vector3(Utils::randRangeInt(0,10000),Utils::randRangeInt(0,10000),Utils::randRangeInt(0,10000));
        dir.normalise();
        this->destination = GestShip::getSingleton()->getAllShips().at(0)->getNode()->getPosition()+dir*1000;
        */
   // }
/*
	if (this->getAcceleration() != 0)
	{
		this->setSpeed(this->getSpeed()+this->getAcceleration());
		this->setAcceleration(0);
	}
	if (this->getSpeed() != 0)
	{
		this->moveRelative(0.0, 0.0, this->getSpeed());
	}*/
}
<commit_msg>Activation des tir de la battle station<commit_after>#include "BattleStation.h"
#include <OgreNode.h>
#include "GestShip.h"
using namespace Ogre;

BattleStation::BattleStation(void) : ShipAbstract(ObjectRoot::SHIP_BATTLE_STATION)
{
    this->typeObject = ObjectRoot::SHIP_BATTLE_STATION;
    this->speed = 0.4;
    this->mRotFrames = 10000;
    this->destination = Ogre::Vector3(130,0,9000);
    mRotating = true;
    mRotFactor = 1;
    mRotProgress = 1;
    this->getNode()->setScale(Ogre::Vector3(0.1,0.1,0.1));
}

BattleStation::~BattleStation(void)
{

}

void BattleStation::updatePosition(void)
{
    Ogre::Vector3 direction = this->getNode()->getPosition()-this->destination;
    //commenté pke bouffeur de FPS = les particules ne meurent pas
    if(direction.squaredLength()<40000000)
    {
		this->shootLaser();
    }

    //Se tourne vers nous plus ou moins (mRotFactor == vitesse à laquelle c fait et avant que le vsx change de destination => inversement proportionnel)
        if(mRotating)
        {
          mRotProgress += mRotFactor;
          if(mRotProgress>1)
          {
              this->destination = GestShip::getSingleton()->getAllShips().at(0)->getNode()->getPosition()+Ogre::Vector3(Utils::randRangeInt(-10000,10000),Utils::randRangeInt(-10000,10000),Utils::randRangeInt(-10000,10000));
              mRotating = false;
              mRotating = true;
              mRotFactor = 1.0f / mRotFrames;
              mOrientSrc = this->getNode()->getOrientation();
              Ogre::Quaternion quat =  (this->getNode()->getOrientation()* Vector3::UNIT_Z).getRotationTo(    this->destination-this->getNode()->getPosition());
              mOrientDest = quat * mOrientSrc;           // We want dest orientation, not a relative rotation (quat)
              mRotProgress = 0;
          }
          else
          {
              //rotation
              Quaternion delta = Quaternion::Slerp(mRotProgress, mOrientSrc, mOrientDest, true);
              this->getNode()->setOrientation(delta);
          }
        }
        //si on est encore loin on avance
        if(direction.squaredLength()>4000000)
        {
            this->setSpeed(speed);

        }else{
            this->setSpeed(0);
        }
             if (this->getSpeed() != 0)
            {
                this->moveRelative(0.0, 0.0, this->getSpeed());
            }
        //TODO:peut etre translaté tjs tout droit par rapport à lui meme et on corrige l'orientation du vsx = effet plus smoothy je pense
   /* }else
    {
        mRotating = true;
        mRotFactor = 1.0f / 10;
        mOrientSrc = this->getNode()->getOrientation();
        Ogre::Quaternion quat =  (this->getNode()->getOrientation()* Vector3::UNIT_X).getRotationTo( GestShip::getSingleton()->getAllShips().at(0)->getNode()->getPosition());
        mOrientDest = quat * mOrientSrc;           // We want dest orientation, not a relative rotation (quat)
        mRotProgress = 0;
        /*
        Ogre::Vector3 dir = Ogre::Vector3(Utils::randRangeInt(0,10000),Utils::randRangeInt(0,10000),Utils::randRangeInt(0,10000));
        dir.normalise();
        this->destination = GestShip::getSingleton()->getAllShips().at(0)->getNode()->getPosition()+dir*1000;
        */
   // }
/*
	if (this->getAcceleration() != 0)
	{
		this->setSpeed(this->getSpeed()+this->getAcceleration());
		this->setAcceleration(0);
	}
	if (this->getSpeed() != 0)
	{
		this->moveRelative(0.0, 0.0, this->getSpeed());
	}*/
}
<|endoftext|>


<commit_before>#pragma once
#include <sstream>
#include <utility>
#include <stdexcept>
#include <boost/current_function.hpp>
#include "detail/Exception.hpp"

namespace But
{

class Exception: public std::runtime_error
{
protected:
  explicit Exception(std::stringstream&& ss): std::runtime_error{ ss.str() } { }

  static std::stringstream   defineBegining(char const* file, unsigned line);
  static std::stringstream&& defineEnding(std::stringstream&& ss, char const* function);
  static std::stringstream&& appendMessage(std::stringstream&& ss, std::string&& msg) { ss << std::move(msg); return std::move(ss); }
  static std::stringstream&& appendDefaultMessage(std::stringstream&& ss) { return std::move(ss); }
};

#define BUT_DEFINE_EXCEPTION(name, base, msgDef) BUT_DEFINE_EXCEPTION_IMPL(name, base, msgDef)

#define BUT_THROW(type, msgExpr) BUT_THROW_IMPL(type, msgExpr)

}
<commit_msg>removed unused header<commit_after>#pragma once
#include <sstream>
#include <utility>
#include <stdexcept>
#include "detail/Exception.hpp"

namespace But
{

class Exception: public std::runtime_error
{
protected:
  explicit Exception(std::stringstream&& ss): std::runtime_error{ ss.str() } { }

  static std::stringstream   defineBegining(char const* file, unsigned line);
  static std::stringstream&& defineEnding(std::stringstream&& ss, char const* function);
  static std::stringstream&& appendMessage(std::stringstream&& ss, std::string&& msg) { ss << std::move(msg); return std::move(ss); }
  static std::stringstream&& appendDefaultMessage(std::stringstream&& ss) { return std::move(ss); }
};

#define BUT_DEFINE_EXCEPTION(name, base, msgDef) BUT_DEFINE_EXCEPTION_IMPL(name, base, msgDef)

#define BUT_THROW(type, msgExpr) BUT_THROW_IMPL(type, msgExpr)

}
<|endoftext|>


<commit_before><commit_msg>break dependency on folly:format<commit_after><|endoftext|>


<commit_before><commit_msg>Add a few more cases for Unicode blocks to script mapping.  This is for next point release (of beta branch) to fix  issue 1328. It includes Hironori's change to add a missing 'break'. ( http://codereview.chromium.org/1698 )  <commit_after><|endoftext|>


<commit_before>#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <err.h>

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "gpio.h"

#define LOW                 0
#define HIGH                1

/* Raspberry Pi GPIO memory */
#define BCM2708_PERI_BASE   0x20000000
#define BCM2709_PERI_BASE   0x3F000000
#define BCM2835_PERI_BASE   0x20000000
#define GPIO_BASE(address)  (address + 0x200000)
#define PAGE_SIZE           (4*1024)
#define BLOCK_SIZE          (4*1024)

/* GPIO setup. Always use INP_GPIO(x) before OUT_GPIO(x) or SET_GPIO_ALT(x,y) */
#define GPIO_MODE_IN(g)     *(_gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define GPIO_MODE_OUT(g)    *(_gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define GPIO_MODE_ALT(g,a)  *(_gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET_HIGH       *(_gpio+7)  // sets   bits which are 1
#define GPIO_SET_LOW        *(_gpio+10) // clears bits which are 1
#define GPIO_GET(g)         (*(_gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH

#define MAX_SIZE_LINE       50

using namespace Navio;

Pin::Pin(uint8_t pin):
    _pin(pin),
    _gpio(NULL),
    _mode(GpioModeInput)
{
}

Pin::~Pin()
{
    if (!_deinit()) {
        warnx("deinitialization failed");
    }
}

bool Pin::_deinit()
{
    if (munmap(const_cast<uint32_t *>(_gpio), BLOCK_SIZE) < 0) {
        warnx("unmap failed");
        return false;
    }
    return true;
}

bool Pin::init()
{
    int mem_fd;
    if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
        warn("/dev/mem cannot be opened");
        return false;
    }

    uint32_t address;
    int version = getRaspberryPiVersion();
    if (version == 1) {
        address = GPIO_BASE(BCM2708_PERI_BASE);
    } else if (version == 2) {
        address = GPIO_BASE(BCM2709_PERI_BASE);
    } else if (version == 3) {
        address = GPIO_BASE(BCM2835_PERI_BASE);
    }

    void *gpio_map = mmap(
        NULL,                 /* any adddress in our space will do */
        BLOCK_SIZE,           /* map length */
        PROT_READ|PROT_WRITE, /* enable reading & writting to mapped memory */
        MAP_SHARED,           /* shared with other processes */
        mem_fd,               /* file to map */
        address               /* offset to GPIO peripheral */
    );

    if (gpio_map == MAP_FAILED) {
        warn("cannot mmap memory");
        return false;
    }

    /* No need to keep mem_fd open after mmap */
    if (close(mem_fd) < 0) {
        warn("cannot close mem_fd");
        return false;
    }

    _gpio = reinterpret_cast<volatile uint32_t *>(gpio_map); // Always use volatile pointer!

    return true;
}

void Pin::setMode(GpioMode mode)
{
    if (mode == GpioModeInput) {
        GPIO_MODE_IN(_pin);
    } else {
        GPIO_MODE_IN(_pin);
        GPIO_MODE_OUT(_pin);
    }

    _mode = mode;
}

uint8_t Pin::read() const
{
    uint32_t value = GPIO_GET(_pin);
    return value ? 1: 0;
}

void Pin::write(uint8_t value)
{
    if (_mode != GpioModeOutput) {
        warnx("no effect because mode is not set");
    }

    if (value == LOW) {
        GPIO_SET_LOW = 1 << _pin;
    } else {
        GPIO_SET_HIGH = 1 << _pin;
    }
}

void Pin::toggle()
{
    write(!read());
}

int Pin::getRaspberryPiVersion() const
{
    char buffer[MAX_SIZE_LINE];
    const char* hardware_description_entry = "Hardware";
    const char* v1 = "BCM2708";
    const char* v2 = "BCM2709";
    const char* v3 = "BCM2835";
    char* flag;
    FILE* fd;

    fd = fopen("/proc/cpuinfo", "r");

    while (fgets(buffer, MAX_SIZE_LINE, fd) != NULL) {
        flag = strstr(buffer, hardware_description_entry);

        if (flag != NULL) {
            if (strstr(buffer, v3) != NULL) {
                fclose(fd);
                return 3;
            } else if (strstr(buffer, v2) != NULL) {
                fclose(fd);
                return 2;
            } else if (strstr(buffer, v1) != NULL) {
                fclose(fd);
                return 1;
            }
        }
    }

    /* defaults to 1 */
    fprintf(stderr, "Could not detect RPi version, defaulting to 1\n");
    fclose(fd);
    return 1;
}
<commit_msg>C++: Navio: Common: fix initialize bug<commit_after>#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <err.h>

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "gpio.h"

#define LOW                 0
#define HIGH                1

/* Raspberry Pi GPIO memory */
#define BCM2708_PERI_BASE   0x20000000
#define BCM2709_PERI_BASE   0x3F000000
#define BCM2835_PERI_BASE   0x3F000000
#define GPIO_BASE(address)  (address + 0x200000)
#define PAGE_SIZE           (4*1024)
#define BLOCK_SIZE          (4*1024)

/* GPIO setup. Always use INP_GPIO(x) before OUT_GPIO(x) or SET_GPIO_ALT(x,y) */
#define GPIO_MODE_IN(g)     *(_gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define GPIO_MODE_OUT(g)    *(_gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define GPIO_MODE_ALT(g,a)  *(_gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET_HIGH       *(_gpio+7)  // sets   bits which are 1
#define GPIO_SET_LOW        *(_gpio+10) // clears bits which are 1
#define GPIO_GET(g)         (*(_gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH

#define MAX_SIZE_LINE       50

using namespace Navio;

Pin::Pin(uint8_t pin):
    _pin(pin),
    _gpio(NULL),
    _mode(GpioModeInput)
{
}

Pin::~Pin()
{
    if (!_deinit()) {
        warnx("deinitialization failed");
    }
}

bool Pin::_deinit()
{
    if (munmap(const_cast<uint32_t *>(_gpio), BLOCK_SIZE) < 0) {
        warnx("unmap failed");
        return false;
    }
    return true;
}

bool Pin::init()
{
    int mem_fd;
    if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
        warn("/dev/mem cannot be opened");
        return false;
    }

    uint32_t address;
    int version = getRaspberryPiVersion();
    if (version == 1) {
        address = GPIO_BASE(BCM2708_PERI_BASE);
    } else if (version == 2) {
        address = GPIO_BASE(BCM2709_PERI_BASE);
    } else if (version == 3) {
        address = GPIO_BASE(BCM2835_PERI_BASE);
    }

    void *gpio_map = mmap(
        NULL,                 /* any adddress in our space will do */
        BLOCK_SIZE,           /* map length */
        PROT_READ|PROT_WRITE, /* enable reading & writting to mapped memory */
        MAP_SHARED,           /* shared with other processes */
        mem_fd,               /* file to map */
        address               /* offset to GPIO peripheral */
    );

    if (gpio_map == MAP_FAILED) {
        warn("cannot mmap memory");
        return false;
    }

    /* No need to keep mem_fd open after mmap */
    if (close(mem_fd) < 0) {
        warn("cannot close mem_fd");
        return false;
    }

    _gpio = reinterpret_cast<volatile uint32_t *>(gpio_map); // Always use volatile pointer!

    return true;
}

void Pin::setMode(GpioMode mode)
{
    if (mode == GpioModeInput) {
        GPIO_MODE_IN(_pin);
    } else {
        GPIO_MODE_IN(_pin);
        GPIO_MODE_OUT(_pin);
    }

    _mode = mode;
}

uint8_t Pin::read() const
{
    uint32_t value = GPIO_GET(_pin);
    return value ? 1: 0;
}

void Pin::write(uint8_t value)
{
    if (_mode != GpioModeOutput) {
        warnx("no effect because mode is not set");
    }

    if (value == LOW) {
        GPIO_SET_LOW = 1 << _pin;
    } else {
        GPIO_SET_HIGH = 1 << _pin;
    }
}

void Pin::toggle()
{
    write(!read());
}

int Pin::getRaspberryPiVersion() const
{
    char buffer[MAX_SIZE_LINE];
    const char* hardware_description_entry = "Hardware";
    const char* v1 = "BCM2708";
    const char* v2 = "BCM2709";
    const char* v3 = "BCM2835";
    char* flag;
    FILE* fd;

    fd = fopen("/proc/cpuinfo", "r");

    while (fgets(buffer, MAX_SIZE_LINE, fd) != NULL) {
        flag = strstr(buffer, hardware_description_entry);

        if (flag != NULL) {
            if (strstr(buffer, v3) != NULL) {
                fclose(fd);
                return 3;
            } else if (strstr(buffer, v2) != NULL) {
                fclose(fd);
                return 2;
            } else if (strstr(buffer, v1) != NULL) {
                fclose(fd);
                return 1;
            }
        }
    }

    /* defaults to 1 */
    fprintf(stderr, "Could not detect RPi version, defaulting to 1\n");
    fclose(fd);
    return 1;
}
<|endoftext|>


<commit_before>
#include <stdexcept>
#include <iostream>
#include <unordered_map>

#include <boost/algorithm/string.hpp>

#include "node/all_nodes.h"
#include "node/nodebypath.h"

#include "block.h"
#include "exception.h"
#include "filehandler.h"
#include "reader.h"
#include "schemareader.h"
#include "stringbuffer.h"
#include "zigzag.hpp"

namespace {
    const std::string AVRO_MAGICK = "Obj\001"; // 4 bytes
}

namespace avro {

class Reader::Private {
public:

    std::unique_ptr<StringBuffer> input;

    FileHandle file;

    Private(const std::string& filename) : file(filename) {
    }
};

Reader::Reader(const std::string& filename) :
    d(new Private(filename)) {

    d->input = d->file.mmapFile();
}

Reader::~Reader() {
    delete d;
}

header Reader::readHeader() {

    std::string magick;
    magick.resize(AVRO_MAGICK.size());
    d->input->read(&magick[0], AVRO_MAGICK.size());

    if (magick != AVRO_MAGICK) {
        throw std::runtime_error("Bad avro file (wrong magick)");
    }

    header header;

    int64_t recordsNumber = readZigZagLong(*d->input);

    for(uint i = 0; i < recordsNumber; ++i) {

        size_t len = readZigZagLong(*d->input);
        const std::string &key = d->input->getStdString(len);
        const std::string &value = d->input->getStdString(readZigZagLong(*d->input));

        header.metadata[key] = value;

    }

    SchemaReader schemaReader(header.metadata["avro.schema"]);
    header.schema = schemaReader.parse();
    header.nodesNumber = schemaReader.nodesNumber();
    //dumpSchema(schemaRoot);

    char c = d->input->getChar();

    assert(c == 0); // TODO: what is it?
    d->input->read(&header.sync[0], sizeof header.sync);

    return header;

}

avro::StringBuffer Reader::nextBlock(const header &header, int64_t &objectCountInBlock ) {

    objectCountInBlock = readZigZagLong(*d->input);
    int64_t blockBytesNum = readZigZagLong(*d->input);

    avro::StringBuffer result(d->input->getAndSkip(blockBytesNum), blockBytesNum);

    char tmp_sync[16] = {0}; // TODO sync length to a constant
    d->input->read(&tmp_sync[0], sizeof tmp_sync); // TODO: move to a function

    if (std::memcmp(tmp_sync, header.sync, sizeof tmp_sync) != 0) {
        throw std::runtime_error("Sync match failed");
    }

    return result;

}

bool Reader::eof() {
    return d->input->eof();
}

void Reader::dumpSchema(const std::unique_ptr<node::Node> &schema, int level) const {
    if (schema->is<node::Record>()) {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << schema->getItemName() << " {\n";
        for(auto &p : schema->as<node::Record>().getChildren()) {
            dumpSchema(p, level + 1);
        }
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << "}\n";
    } else if (schema->is<node::Union>()) {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << schema->getItemName() << ":[\n";
        for(auto &p : schema->as<node::Union>().getChildren()) {
            dumpSchema(p, level + 1);
        }
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << "]\n";
    } else if (schema->is<node::Custom>()) {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << schema->getItemName() << ":" << schema->getTypeName() << std::endl;
        dumpSchema(schema->as<node::Custom>().getDefinition(), level + 1);
    } else {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        // std::cout << schema->getItemName() << ":" << schema->getTypeName() << std::endl;
    }
}

dumper::TsvExpression Reader::compileFieldsList(const std::string &filedList, const header &header, const std::string &fieldSeparator) {

    std::vector<std::string> fields;
    boost::algorithm::split(fields, filedList, boost::is_any_of(","));

    dumper::TsvExpression result;
    result.pos = 0;
    result.fieldSeparator = fieldSeparator;

    if (filedList.empty()) {
    	return result;
    }

    for(auto p = fields.begin(); p != fields.end(); ++p) {
        auto node = schemaNodeByPath(*p, header);

        if (node->is<node::Custom>()) {
            node = node->as<node::Custom>().getDefinition().get();
        }

        result.what[node->getNumber()] = result.pos;
        if (node->is<node::Union>()) {
        	for( auto &p : node->as<node::Union>().getChildren()) {
        		result.what[p->getNumber()] = result.pos;
        	}
        }
        result.pos++;
    }

    return result;

}

const node::Node* Reader::schemaNodeByPath(const std::string &path, const header &header) {
    auto n = node::nodeByPath(path, header.schema.get());
    if (n == nullptr) {
        throw PathNotFound(path);
    }
    return n;
}

}

<commit_msg>Correct message when trying to use array/map in TSV expression<commit_after>
#include <stdexcept>
#include <iostream>
#include <unordered_map>

#include <boost/algorithm/string.hpp>

#include "node/all_nodes.h"
#include "node/nodebypath.h"

#include "block.h"
#include "exception.h"
#include "filehandler.h"
#include "reader.h"
#include "schemareader.h"
#include "stringbuffer.h"
#include "zigzag.hpp"

namespace {
    const std::string AVRO_MAGICK = "Obj\001"; // 4 bytes
}

namespace avro {

class Reader::Private {
public:

    std::unique_ptr<StringBuffer> input;

    FileHandle file;

    Private(const std::string& filename) : file(filename) {
    }
};

Reader::Reader(const std::string& filename) :
    d(new Private(filename)) {

    d->input = d->file.mmapFile();
}

Reader::~Reader() {
    delete d;
}

header Reader::readHeader() {

    std::string magick;
    magick.resize(AVRO_MAGICK.size());
    d->input->read(&magick[0], AVRO_MAGICK.size());

    if (magick != AVRO_MAGICK) {
        throw std::runtime_error("Bad avro file (wrong magick)");
    }

    header header;

    int64_t recordsNumber = readZigZagLong(*d->input);

    for(uint i = 0; i < recordsNumber; ++i) {

        size_t len = readZigZagLong(*d->input);
        const std::string &key = d->input->getStdString(len);
        const std::string &value = d->input->getStdString(readZigZagLong(*d->input));

        header.metadata[key] = value;

    }

    SchemaReader schemaReader(header.metadata["avro.schema"]);
    header.schema = schemaReader.parse();
    header.nodesNumber = schemaReader.nodesNumber();
    //dumpSchema(schemaRoot);

    char c = d->input->getChar();

    assert(c == 0); // TODO: what is it?
    d->input->read(&header.sync[0], sizeof header.sync);

    return header;

}

avro::StringBuffer Reader::nextBlock(const header &header, int64_t &objectCountInBlock ) {

    objectCountInBlock = readZigZagLong(*d->input);
    int64_t blockBytesNum = readZigZagLong(*d->input);

    avro::StringBuffer result(d->input->getAndSkip(blockBytesNum), blockBytesNum);

    char tmp_sync[16] = {0}; // TODO sync length to a constant
    d->input->read(&tmp_sync[0], sizeof tmp_sync); // TODO: move to a function

    if (std::memcmp(tmp_sync, header.sync, sizeof tmp_sync) != 0) {
        throw std::runtime_error("Sync match failed");
    }

    return result;

}

bool Reader::eof() {
    return d->input->eof();
}

void Reader::dumpSchema(const std::unique_ptr<node::Node> &schema, int level) const {
    if (schema->is<node::Record>()) {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << schema->getItemName() << " {\n";
        for(auto &p : schema->as<node::Record>().getChildren()) {
            dumpSchema(p, level + 1);
        }
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << "}\n";
    } else if (schema->is<node::Union>()) {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << schema->getItemName() << ":[\n";
        for(auto &p : schema->as<node::Union>().getChildren()) {
            dumpSchema(p, level + 1);
        }
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << "]\n";
    } else if (schema->is<node::Custom>()) {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        std::cout << schema->getItemName() << ":" << schema->getTypeName() << std::endl;
        dumpSchema(schema->as<node::Custom>().getDefinition(), level + 1);
    } else {
        for(int i = 0; i < level; ++i) {
            std::cout << "\t";
        }
        // std::cout << schema->getItemName() << ":" << schema->getTypeName() << std::endl;
    }
}

const node::Node *notArrayNorMap(
        const node::Node *node,
        const std::string &path) {

    if (node->isOneOf<node::Array, node::Map>()) {
        throw std::runtime_error(
            "Sorry, but type '" + node->getTypeName() +
            "' for field '" + path + "' "
            "Is not yet supported in tsv expression.");

    } else if (node->is<node::Custom>()) {
        auto &p = node->as<node::Custom>().getDefinition();
        return notArrayNorMap(p.get(), path);
    }
    return node;
}

dumper::TsvExpression Reader::compileFieldsList(const std::string &filedList, const header &header, const std::string &fieldSeparator) {

    std::vector<std::string> fields;
    boost::algorithm::split(fields, filedList, boost::is_any_of(","));

    dumper::TsvExpression result;
    result.pos = 0;
    result.fieldSeparator = fieldSeparator;

    if (filedList.empty()) {
    	return result;
    }

    for(auto p = fields.begin(); p != fields.end(); ++p) {
        auto node = schemaNodeByPath(*p, header);

        if (node->is<node::Custom>()) {
            node = node->as<node::Custom>().getDefinition().get();
        }

        result.what[notArrayNorMap(node, *p)->getNumber()] = result.pos;
        if (node->is<node::Union>()) {
            for( auto &n : node->as<node::Union>().getChildren()) {
                result.what[notArrayNorMap(n.get(), *p)->getNumber()] = result.pos;
            }
        }
        result.pos++;
    }

    return result;

}

const node::Node* Reader::schemaNodeByPath(const std::string &path, const header &header) {
    auto n = node::nodeByPath(path, header.schema.get());
    if (n == nullptr) {
        throw PathNotFound(path);
    }
    return n;
}

}

<|endoftext|>


<commit_before>/* This file is part of VoltDB.
 * Copyright (C) 2008-2016 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef EE_COMMON_GEOGRAPHY_POINT_VALUE_HPP
#define EE_COMMON_GEOGRAPHY_POINT_VALUE_HPP

#include <limits>
#include <sstream>

#include "common/MiscUtil.h"
#include "common/value_defs.h"

#include "s2geo/s2.h"
#include "s2geo/s2latlng.h"

namespace voltdb {
/**
 * A class for representing instances of geo-spatial points.
 */
class GeographyPointValue {
public:

    typedef double Coord;

    /** Constructor for a null point,
     * with both lng and lat initialized to the null coordinate */
    GeographyPointValue()
        : m_latitude(nullCoord())
        , m_longitude(nullCoord())
    {
    }

    GeographyPointValue(Coord longitude, Coord latitude)
        : m_latitude(latitude)
        , m_longitude(longitude)
    {
        assert (m_latitude >= -90.0 && m_latitude <= 90.0);
        assert (m_longitude >= -180.0 && m_longitude <= 180.0);
    }

    GeographyPointValue(const S2Point &s2Point)
        : m_latitude(nullCoord())
        , m_longitude(nullCoord())
    {
        assert(!s2Point.IsNaN());
        S2LatLng latLong(s2Point);
        m_latitude = latLong.lat().degrees();
        m_longitude = latLong.lng().degrees();
        assert (m_latitude >= -90.0 && m_latitude <= 90.0);
        assert (m_longitude >= -180.0 && m_longitude <= 180.0);
    }

    // Use the number 360.0 for the null coordinate.
    static Coord nullCoord() {
        // A static const member could be used for this, but clang
        // wants the constexpr keyword to be used with floating-point
        // constants, and constexpr isn't supported until gcc 4.6.
        // Creating a static function seems nicer than suppressing the
        // warning or using the conditional compilation.
        return 360.0;
    }

    // Due to conversion to and from (x,y,z) coordinates needed to
    // support our polygon representation, we consider points whose
    // coordinates vary by less than this epsilon to be equal.  This
    // function should return a value that is the same as in Java
    // code: GeographyPointValue.EPSILON.
    static Coord epsilon() {
        // Making this a static method rather than a static member
        // variable for the same reason as nullCoord(), above.
        return 1e-12;
    }

    // The null point has 360 for both lat and long.
    bool isNull() const {
        return (m_latitude == nullCoord()) &&
            (m_longitude == nullCoord());
    }

    Coord getLatitude() const {
        return m_latitude;
    }

    Coord getLongitude() const {
        return m_longitude;
    }

    S2Point toS2Point() const {
        return S2LatLng::FromDegrees(getLatitude(), getLongitude()).ToPoint();
    }

    int compareWith(const GeographyPointValue& rhs) const {

        // Caller guarantees that neither side is null
        assert(! isNull());
        assert(! rhs.isNull());

        const GeographyPointValue canonThis = canonicalize();
        const GeographyPointValue canonRhs = rhs.canonicalize();
        Coord lhsLong = canonThis.getLongitude();
        Coord rhsLong = canonRhs.getLongitude();
        if (rhsLong - lhsLong > epsilon()) {
            return VALUE_COMPARE_LESSTHAN;
        }

        if (lhsLong - rhsLong > epsilon()) {
            return VALUE_COMPARE_GREATERTHAN;
        }

        // latitude is equal; compare longitude
        Coord lhsLat = canonThis.getLatitude();
        Coord rhsLat = canonRhs.getLatitude();
        if (rhsLat - lhsLat > epsilon()) {
            return VALUE_COMPARE_LESSTHAN;
        }

        if (lhsLat - rhsLat > epsilon()) {
            return VALUE_COMPARE_GREATERTHAN;
        }

        return VALUE_COMPARE_EQUAL;
    }

    template<class Deserializer>
    static GeographyPointValue deserializeFrom(Deserializer& input) {
        Coord lng = input.readDouble();
        Coord lat = input.readDouble();
        if (lat == nullCoord() && lng == nullCoord()) {
            return GeographyPointValue();
        }

        return GeographyPointValue(lng, lat);
    }

    template<class Serializer>
    void serializeTo(Serializer& output) const {
        output.writeDouble(getLongitude());
        output.writeDouble(getLatitude());
    }

    void hashCombine(std::size_t& seed) const {
        MiscUtil::hashCombineFloatingPoint(seed, m_longitude);
        MiscUtil::hashCombineFloatingPoint(seed, m_latitude);
    }

    std::string toString() const {
        std::ostringstream oss;
        oss << "point(" << m_longitude << " " << m_latitude << ")";
        return oss.str();
    }

    std::string formatLngLat() const {
        std::ostringstream oss;
        oss << toString(m_longitude) << " " << toString(m_latitude);
        return oss.str();
    }

    // returns wkt representation for given point: "POINT (<Longitude> <Latitude>)"
    std::string toWKT() const {
        std::ostringstream oss;
        oss <<"POINT (" << formatLngLat() << ")";
        return oss.str();
    }

private:
    // converts double value to string with specified precision displaying
    // only significant decimal value.
    // Output pattern is similar to "...##0.0##..."
    std::string toString(double number) const {
        char buffer[32];
        const int8_t decimalPrecision = 12;

        bool wholeNumber = isWholeNumberWithRounding(number);
        if (wholeNumber) {
            snprintf(buffer, sizeof(buffer), "%3.1f", number);
        }
        else {
            int wholeNumberDigits = log10(abs(number)) + 1;
            snprintf(buffer, sizeof(buffer), "%.*g", (wholeNumberDigits + decimalPrecision), number);
        }
        return buffer;
    }

    // function checks if the given number is whole number taking into account
    // rounding to 12 decimal digit precision
    bool isWholeNumberWithRounding(double number) const {
        const int8_t decimalPrecision = 12;

        // check if it's whole number
        if (number == floor(number)) {
            return true;
        }

        // check if rounded value is a whole number
        double shiftNum = pow(10, decimalPrecision);
        double roundedNumber = ceil((number * shiftNum) - 0.4999999) / shiftNum;
        if (roundedNumber == floor(roundedNumber)) {
            return true;
        }

        // decimal number
        return false;
    }

    // return a point that is equivalent to this but make sure that
    // longitude is always 0 at either pole, and longitude of -180 is
    // converted to 180.  Canonicalized points whose coordinates are
    // within epsilon of each other are equal.
    GeographyPointValue canonicalize() const {
        Coord newLng = m_longitude;

        if (90.0 - fabs(m_latitude) < epsilon()) {
            // We are at one of the poles;
            // longitude doesn't matter, so choose 0.
            newLng = 0.0;
        }

        // If point is not at the poles, evaluate longitudes within epsilon
        // of the antimeridian (on the east side), canonicalize to 180.0.
        else if (180.0 + m_longitude < epsilon()) {
            newLng = 180.0;
        }

        return GeographyPointValue(newLng, m_latitude);
    }

    Coord m_latitude;
    Coord m_longitude;
};

} // end namespace

#endif // EE_COMMON_GEOGRAPHY_POINT_VALUE_HPP
<commit_msg>update comment style around if/else block changes as per Chris review feedback<commit_after>/* This file is part of VoltDB.
 * Copyright (C) 2008-2016 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef EE_COMMON_GEOGRAPHY_POINT_VALUE_HPP
#define EE_COMMON_GEOGRAPHY_POINT_VALUE_HPP

#include <limits>
#include <sstream>

#include "common/MiscUtil.h"
#include "common/value_defs.h"

#include "s2geo/s2.h"
#include "s2geo/s2latlng.h"

namespace voltdb {
/**
 * A class for representing instances of geo-spatial points.
 */
class GeographyPointValue {
public:

    typedef double Coord;

    /** Constructor for a null point,
     * with both lng and lat initialized to the null coordinate */
    GeographyPointValue()
        : m_latitude(nullCoord())
        , m_longitude(nullCoord())
    {
    }

    GeographyPointValue(Coord longitude, Coord latitude)
        : m_latitude(latitude)
        , m_longitude(longitude)
    {
        assert (m_latitude >= -90.0 && m_latitude <= 90.0);
        assert (m_longitude >= -180.0 && m_longitude <= 180.0);
    }

    GeographyPointValue(const S2Point &s2Point)
        : m_latitude(nullCoord())
        , m_longitude(nullCoord())
    {
        assert(!s2Point.IsNaN());
        S2LatLng latLong(s2Point);
        m_latitude = latLong.lat().degrees();
        m_longitude = latLong.lng().degrees();
        assert (m_latitude >= -90.0 && m_latitude <= 90.0);
        assert (m_longitude >= -180.0 && m_longitude <= 180.0);
    }

    // Use the number 360.0 for the null coordinate.
    static Coord nullCoord() {
        // A static const member could be used for this, but clang
        // wants the constexpr keyword to be used with floating-point
        // constants, and constexpr isn't supported until gcc 4.6.
        // Creating a static function seems nicer than suppressing the
        // warning or using the conditional compilation.
        return 360.0;
    }

    // Due to conversion to and from (x,y,z) coordinates needed to
    // support our polygon representation, we consider points whose
    // coordinates vary by less than this epsilon to be equal.  This
    // function should return a value that is the same as in Java
    // code: GeographyPointValue.EPSILON.
    static Coord epsilon() {
        // Making this a static method rather than a static member
        // variable for the same reason as nullCoord(), above.
        return 1e-12;
    }

    // The null point has 360 for both lat and long.
    bool isNull() const {
        return (m_latitude == nullCoord()) &&
            (m_longitude == nullCoord());
    }

    Coord getLatitude() const {
        return m_latitude;
    }

    Coord getLongitude() const {
        return m_longitude;
    }

    S2Point toS2Point() const {
        return S2LatLng::FromDegrees(getLatitude(), getLongitude()).ToPoint();
    }

    int compareWith(const GeographyPointValue& rhs) const {

        // Caller guarantees that neither side is null
        assert(! isNull());
        assert(! rhs.isNull());

        const GeographyPointValue canonThis = canonicalize();
        const GeographyPointValue canonRhs = rhs.canonicalize();
        Coord lhsLong = canonThis.getLongitude();
        Coord rhsLong = canonRhs.getLongitude();
        if (rhsLong - lhsLong > epsilon()) {
            return VALUE_COMPARE_LESSTHAN;
        }

        if (lhsLong - rhsLong > epsilon()) {
            return VALUE_COMPARE_GREATERTHAN;
        }

        // latitude is equal; compare longitude
        Coord lhsLat = canonThis.getLatitude();
        Coord rhsLat = canonRhs.getLatitude();
        if (rhsLat - lhsLat > epsilon()) {
            return VALUE_COMPARE_LESSTHAN;
        }

        if (lhsLat - rhsLat > epsilon()) {
            return VALUE_COMPARE_GREATERTHAN;
        }

        return VALUE_COMPARE_EQUAL;
    }

    template<class Deserializer>
    static GeographyPointValue deserializeFrom(Deserializer& input) {
        Coord lng = input.readDouble();
        Coord lat = input.readDouble();
        if (lat == nullCoord() && lng == nullCoord()) {
            return GeographyPointValue();
        }

        return GeographyPointValue(lng, lat);
    }

    template<class Serializer>
    void serializeTo(Serializer& output) const {
        output.writeDouble(getLongitude());
        output.writeDouble(getLatitude());
    }

    void hashCombine(std::size_t& seed) const {
        MiscUtil::hashCombineFloatingPoint(seed, m_longitude);
        MiscUtil::hashCombineFloatingPoint(seed, m_latitude);
    }

    std::string toString() const {
        std::ostringstream oss;
        oss << "point(" << m_longitude << " " << m_latitude << ")";
        return oss.str();
    }

    std::string formatLngLat() const {
        std::ostringstream oss;
        oss << toString(m_longitude) << " " << toString(m_latitude);
        return oss.str();
    }

    // returns wkt representation for given point: "POINT (<Longitude> <Latitude>)"
    std::string toWKT() const {
        std::ostringstream oss;
        oss <<"POINT (" << formatLngLat() << ")";
        return oss.str();
    }

private:
    // converts double value to string with specified precision displaying
    // only significant decimal value.
    // Output pattern is similar to "...##0.0##..."
    std::string toString(double number) const {
        char buffer[32];
        const int8_t decimalPrecision = 12;

        bool wholeNumber = isWholeNumberWithRounding(number);
        if (wholeNumber) {
            snprintf(buffer, sizeof(buffer), "%3.1f", number);
        }
        else {
            int wholeNumberDigits = log10(abs(number)) + 1;
            snprintf(buffer, sizeof(buffer), "%.*g", (wholeNumberDigits + decimalPrecision), number);
        }
        return buffer;
    }

    // function checks if the given number is whole number taking into account
    // rounding to 12 decimal digit precision
    bool isWholeNumberWithRounding(double number) const {
        const int8_t decimalPrecision = 12;

        // check if it's whole number
        if (number == floor(number)) {
            return true;
        }

        // check if rounded value is a whole number
        double shiftNum = pow(10, decimalPrecision);
        double roundedNumber = ceil((number * shiftNum) - 0.4999999) / shiftNum;
        if (roundedNumber == floor(roundedNumber)) {
            return true;
        }

        // decimal number
        return false;
    }

    // return a point that is equivalent to this but make sure that
    // longitude is always 0 at either pole, and longitude of -180 is
    // converted to 180.  Canonicalized points whose coordinates are
    // within epsilon of each other are equal.
    GeographyPointValue canonicalize() const {
        Coord newLng = m_longitude;

        if (90.0 - fabs(m_latitude) < epsilon()) {
            // We are at one of the poles;
            // longitude doesn't matter, so choose 0.
            newLng = 0.0;
        }
        else if (180.0 + m_longitude < epsilon()) {
            // If point is not at the poles, evaluate longitudes within epsilon
            // of the antimeridian (on the east side), canonicalize to 180.0.
            newLng = 180.0;
        }

        return GeographyPointValue(newLng, m_latitude);
    }

    Coord m_latitude;
    Coord m_longitude;
};

} // end namespace

#endif // EE_COMMON_GEOGRAPHY_POINT_VALUE_HPP
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPointSet.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkPointSet.h"
#include "vtkSource.h"

vtkPointSet::vtkPointSet ()
{
  this->Points = NULL;
  this->Locator = NULL;
}

//----------------------------------------------------------------------------
vtkPointSet::~vtkPointSet ()
{
  this->Initialize();
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
}

//----------------------------------------------------------------------------
// Copy the geometric structure of an input point set object.
void vtkPointSet::CopyStructure(vtkDataSet *ds)
{
  vtkPointSet *ps=(vtkPointSet *)ds;
  this->Initialize();

  this->SetPoints(ps->Points);
}

//----------------------------------------------------------------------------
void vtkPointSet::Initialize()
{
  vtkDataSet::Initialize();

  if ( this->Points )
    {
    this->Points->UnRegister(this);
    this->Points = NULL;
    }

  if ( this->Locator )
    {
    this->Locator->Initialize();
    }
}
//----------------------------------------------------------------------------
void vtkPointSet::ComputeBounds()
{
  float *bounds;

  if ( this->Points )
    {
    bounds = this->Points->GetBounds();
    for (int i=0; i<6; i++)
      {
      this->Bounds[i] = bounds[i];
      }
    this->ComputeTime.Modified();
    }
}

//----------------------------------------------------------------------------
unsigned long int vtkPointSet::GetMTime()
{
  unsigned long int dsTime = vtkDataSet::GetMTime();

  if ( this->Points )
    {
    if ( this->Points->GetMTime() > dsTime )
      {
      dsTime = this->Points->GetMTime();
      }
    }

  // don't get locator's mtime because its an internal object that cannot be
  // modified directly from outside. Causes problems due to FindCell()
  // SetPoints() method.

  return dsTime;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindPoint(float x[3])
{
  if ( !this->Points )
    {
    return -1;
    }

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->SetDataSet(this);
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    }

  return this->Locator->FindClosestPoint(x);
}

//the furthest the walk can be - prevents aimless wandering
#define VTK_MAX_WALK 12

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(float x[3], vtkCell *cell,
                                vtkGenericCell *gencell, vtkIdType cellId,
                                float tol2, int& subId, float pcoords[3],
                                float *weights)
{
  vtkIdType       ptId;
  int             walk;
  float           closestPoint[3];
  float           dist2;
  vtkIdList       *cellIds, *ptIds;
  int             initialCellProvided = 1;

  // make sure everything is up to snuff
  if ( !this->Points )
    {
    return -1;
    }

  cellIds = vtkIdList::New();
  cellIds->Allocate(8,100);
  ptIds = vtkIdList::New();
  ptIds->Allocate(8,100);

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->SetDataSet(this);
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    }

  // If we don't have a starting cell, we'll have to find one. Find
  // the closest point to the input position, then get the cells that use
  // the point.  Then use one of the cells to begin the walking process.
  if ( !cell )
    {
    initialCellProvided = 0;
    ptId = this->Locator->FindClosestPoint(x);
    if ( ptId < 0 )
      {
      cellIds->Delete();
      ptIds->Delete();
      return (-1); //if point completely outside of data
      }

    this->GetPointCells(ptId, cellIds);
    if ( cellIds->GetNumberOfIds() > 0 )
      {
      cellId = cellIds->GetId(0); //arbitrarily use first cell in list
      if ( gencell )
	{
	this->GetCell(cellId, gencell);
	}
      else
	{
	cell = this->GetCell(cellId);
	}

      // See whether this randomly choosen cell contains the point
      if ( ( gencell &&
	     gencell->EvaluatePosition(x,closestPoint,subId,
				       pcoords, dist2,weights) == 1
	     && dist2 <= tol2 )  ||
	   ( !gencell &&
	     cell->EvaluatePosition(x,closestPoint,subId,
				       pcoords, dist2,weights) == 1
	     && dist2 <= tol2 ) )
        {
	cellIds->Delete();
	ptIds->Delete();
        return cellId;
        }
      }
    }
  else //EvaluatePosition insures that pcoords is defined
    {
    cell->EvaluatePosition(x,NULL,subId,pcoords,dist2,weights);
    }

  // If a cell is supplied, or we didn't find a starting cell (in the
  // previous chunk of code), then we use this to start our search. A
  // walking scheme is used, where we walk towards the point and eventually
  // locate the cell that contains the point.
  if ( cell || cellIds->GetNumberOfIds() > 0 ) //we have a starting cell
    {
    for ( walk=0; walk < VTK_MAX_WALK; walk++ )
      {
      if ( cell )
	{
	cell->CellBoundary(subId, pcoords, ptIds);
	}
      else
	{
	gencell->CellBoundary(subId, pcoords, ptIds);
	}
      this->GetCellNeighbors(cellId, ptIds, cellIds);
      if ( cellIds->GetNumberOfIds() > 0 )
        {
        cellId = cellIds->GetId(0);
	if ( gencell )
	  {
	  cell = NULL;
	  this->GetCell(cellId, gencell);
	  }
	else
	  {
	  cell = this->GetCell(cellId);
	  }
        }
      else
        {
        break; //outside of data
        }

      if ( ( (!cell &&
	      gencell->EvaluatePosition(x,closestPoint,subId,pcoords,
					dist2,weights) == 1 ) ||
	     (cell && cell->EvaluatePosition(x,closestPoint,
						 subId,pcoords,
						 dist2,weights) == 1 ) )
	   && dist2 <= tol2 )
        {
	cellIds->Delete();
	ptIds->Delete();
        return cellId;
        }

      }//for a walk
    }//if we have a starting cell

  cellIds->Delete();
  ptIds->Delete();

  //sometimes the initial cell is a really bad guess so we'll
  //just ignore it and start from scratch as a last resort
  if ( initialCellProvided )
    {
    return this->FindCell(x, NULL, gencell, cellId, tol2,
                          subId, pcoords, weights);
    }
  else
    {
    return -1;
    }
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(float x[3], vtkCell *cell, vtkIdType cellId,
                                float tol2, int& subId, float pcoords[3],
                                float *weights)
{
  return
    this->FindCell( x, cell, NULL, cellId, tol2, subId, pcoords, weights );
}

#undef VTK_MAX_WALK

//----------------------------------------------------------------------------
void vtkPointSet::Squeeze()
{
  if ( this->Points )
    {
    this->Points->Squeeze();
    }
  vtkDataSet::Squeeze();
}

//----------------------------------------------------------------------------
void vtkPointSet::UnRegister(vtkObject *o)
{
  // detect the circular loop source <-> data
  // If we have two references and one of them is my data
  // and I am not being unregistered by my data, break the loop.
  if (this->ReferenceCount == 2 && this->Source != NULL &&
      o != this->Source && this->Source->InRegisterLoop(this))
    {
    this->SetSource(NULL);
    }
  // detect the circular loop PointSet <-> Locator
  // If we have two references and one of them is my locator
  // and I am not being unregistered by my locator, break the loop.
  if (this->ReferenceCount == 2 && this->Locator &&
      this->Locator->GetDataSet() == this &&
      this->Locator != o)
    {
    this->Locator->SetDataSet(NULL);
    }
  // catch the case when both of the above are true
  if (this->ReferenceCount == 3 && this->Source != NULL &&
      o != this->Source && this->Source->InRegisterLoop(this) &&
      this->Locator &&
      this->Locator->GetDataSet() == this &&
      this->Locator != o)
    {
    this->SetSource(NULL);
    if (this->Locator)
      {
      this->Locator->SetDataSet(NULL);
      }
    }

  this->vtkObject::UnRegister(o);
}

//----------------------------------------------------------------------------
int vtkPointSet::GetNetReferenceCount()
{
  if (this->Locator && this->Locator->GetDataSet() == this)
    {
    return this->ReferenceCount - 1;
    }
  return this->ReferenceCount;
}

//----------------------------------------------------------------------------
unsigned long vtkPointSet::GetActualMemorySize()
{
  unsigned long size=this->vtkDataSet::GetActualMemorySize();
  if ( this->Points )
    {
    size += this->Points->GetActualMemorySize();
    }
  return size;
}

//----------------------------------------------------------------------------
void vtkPointSet::ShallowCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    this->SetPoints(pointSet->GetPoints());
    }

  // Do superclass
  this->vtkDataSet::ShallowCopy(dataObject);
}

//----------------------------------------------------------------------------
void vtkPointSet::DeepCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    if (this->Points == NULL)
      {
      this->Points = vtkPoints::New();
      }
    this->Points->DeepCopy(pointSet->GetPoints());
    }

  // Do superclass
  this->vtkDataSet::DeepCopy(dataObject);
}

//----------------------------------------------------------------------------
void vtkPointSet::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSet::PrintSelf(os,indent);

  os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n";
  os << indent << "Point Coordinates: " << this->Points << "\n";
  os << indent << "Locator: " << this->Locator << "\n";
}

<commit_msg>ERR:Hard tabs removed<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPointSet.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkPointSet.h"
#include "vtkSource.h"

vtkPointSet::vtkPointSet ()
{
  this->Points = NULL;
  this->Locator = NULL;
}

//----------------------------------------------------------------------------
vtkPointSet::~vtkPointSet ()
{
  this->Initialize();
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
}

//----------------------------------------------------------------------------
// Copy the geometric structure of an input point set object.
void vtkPointSet::CopyStructure(vtkDataSet *ds)
{
  vtkPointSet *ps=(vtkPointSet *)ds;
  this->Initialize();

  this->SetPoints(ps->Points);
}

//----------------------------------------------------------------------------
void vtkPointSet::Initialize()
{
  vtkDataSet::Initialize();

  if ( this->Points )
    {
    this->Points->UnRegister(this);
    this->Points = NULL;
    }

  if ( this->Locator )
    {
    this->Locator->Initialize();
    }
}
//----------------------------------------------------------------------------
void vtkPointSet::ComputeBounds()
{
  float *bounds;

  if ( this->Points )
    {
    bounds = this->Points->GetBounds();
    for (int i=0; i<6; i++)
      {
      this->Bounds[i] = bounds[i];
      }
    this->ComputeTime.Modified();
    }
}

//----------------------------------------------------------------------------
unsigned long int vtkPointSet::GetMTime()
{
  unsigned long int dsTime = vtkDataSet::GetMTime();

  if ( this->Points )
    {
    if ( this->Points->GetMTime() > dsTime )
      {
      dsTime = this->Points->GetMTime();
      }
    }

  // don't get locator's mtime because its an internal object that cannot be
  // modified directly from outside. Causes problems due to FindCell()
  // SetPoints() method.

  return dsTime;
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindPoint(float x[3])
{
  if ( !this->Points )
    {
    return -1;
    }

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->SetDataSet(this);
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    }

  return this->Locator->FindClosestPoint(x);
}

//the furthest the walk can be - prevents aimless wandering
#define VTK_MAX_WALK 12

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(float x[3], vtkCell *cell,
                                vtkGenericCell *gencell, vtkIdType cellId,
                                float tol2, int& subId, float pcoords[3],
                                float *weights)
{
  vtkIdType       ptId;
  int             walk;
  float           closestPoint[3];
  float           dist2;
  vtkIdList       *cellIds, *ptIds;
  int             initialCellProvided = 1;

  // make sure everything is up to snuff
  if ( !this->Points )
    {
    return -1;
    }

  cellIds = vtkIdList::New();
  cellIds->Allocate(8,100);
  ptIds = vtkIdList::New();
  ptIds->Allocate(8,100);

  if ( !this->Locator )
    {
    this->Locator = vtkPointLocator::New();
    this->Locator->SetDataSet(this);
    }

  if ( this->Points->GetMTime() > this->Locator->GetMTime() )
    {
    this->Locator->SetDataSet(this);
    }

  // If we don't have a starting cell, we'll have to find one. Find
  // the closest point to the input position, then get the cells that use
  // the point.  Then use one of the cells to begin the walking process.
  if ( !cell )
    {
    initialCellProvided = 0;
    ptId = this->Locator->FindClosestPoint(x);
    if ( ptId < 0 )
      {
      cellIds->Delete();
      ptIds->Delete();
      return (-1); //if point completely outside of data
      }

    this->GetPointCells(ptId, cellIds);
    if ( cellIds->GetNumberOfIds() > 0 )
      {
      cellId = cellIds->GetId(0); //arbitrarily use first cell in list
      if ( gencell )
        {
        this->GetCell(cellId, gencell);
        }
      else
        {
        cell = this->GetCell(cellId);
        }

      // See whether this randomly choosen cell contains the point
      if ( ( gencell &&
             gencell->EvaluatePosition(x,closestPoint,subId,
                                       pcoords, dist2,weights) == 1
             && dist2 <= tol2 )  ||
           ( !gencell &&
             cell->EvaluatePosition(x,closestPoint,subId,
                                       pcoords, dist2,weights) == 1
             && dist2 <= tol2 ) )
        {
        cellIds->Delete();
        ptIds->Delete();
        return cellId;
        }
      }
    }
  else //EvaluatePosition insures that pcoords is defined
    {
    cell->EvaluatePosition(x,NULL,subId,pcoords,dist2,weights);
    }

  // If a cell is supplied, or we didn't find a starting cell (in the
  // previous chunk of code), then we use this to start our search. A
  // walking scheme is used, where we walk towards the point and eventually
  // locate the cell that contains the point.
  if ( cell || cellIds->GetNumberOfIds() > 0 ) //we have a starting cell
    {
    for ( walk=0; walk < VTK_MAX_WALK; walk++ )
      {
      if ( cell )
        {
        cell->CellBoundary(subId, pcoords, ptIds);
        }
      else
        {
        gencell->CellBoundary(subId, pcoords, ptIds);
        }
      this->GetCellNeighbors(cellId, ptIds, cellIds);
      if ( cellIds->GetNumberOfIds() > 0 )
        {
        cellId = cellIds->GetId(0);
        if ( gencell )
          {
          cell = NULL;
          this->GetCell(cellId, gencell);
          }
        else
          {
          cell = this->GetCell(cellId);
          }
        }
      else
        {
        break; //outside of data
        }

      if ( ( (!cell &&
              gencell->EvaluatePosition(x,closestPoint,subId,pcoords,
                                        dist2,weights) == 1 ) ||
             (cell && cell->EvaluatePosition(x,closestPoint,
                                                 subId,pcoords,
                                                 dist2,weights) == 1 ) )
           && dist2 <= tol2 )
        {
        cellIds->Delete();
        ptIds->Delete();
        return cellId;
        }

      }//for a walk
    }//if we have a starting cell

  cellIds->Delete();
  ptIds->Delete();

  //sometimes the initial cell is a really bad guess so we'll
  //just ignore it and start from scratch as a last resort
  if ( initialCellProvided )
    {
    return this->FindCell(x, NULL, gencell, cellId, tol2,
                          subId, pcoords, weights);
    }
  else
    {
    return -1;
    }
}

//----------------------------------------------------------------------------
vtkIdType vtkPointSet::FindCell(float x[3], vtkCell *cell, vtkIdType cellId,
                                float tol2, int& subId, float pcoords[3],
                                float *weights)
{
  return
    this->FindCell( x, cell, NULL, cellId, tol2, subId, pcoords, weights );
}

#undef VTK_MAX_WALK

//----------------------------------------------------------------------------
void vtkPointSet::Squeeze()
{
  if ( this->Points )
    {
    this->Points->Squeeze();
    }
  vtkDataSet::Squeeze();
}

//----------------------------------------------------------------------------
void vtkPointSet::UnRegister(vtkObject *o)
{
  // detect the circular loop source <-> data
  // If we have two references and one of them is my data
  // and I am not being unregistered by my data, break the loop.
  if (this->ReferenceCount == 2 && this->Source != NULL &&
      o != this->Source && this->Source->InRegisterLoop(this))
    {
    this->SetSource(NULL);
    }
  // detect the circular loop PointSet <-> Locator
  // If we have two references and one of them is my locator
  // and I am not being unregistered by my locator, break the loop.
  if (this->ReferenceCount == 2 && this->Locator &&
      this->Locator->GetDataSet() == this &&
      this->Locator != o)
    {
    this->Locator->SetDataSet(NULL);
    }
  // catch the case when both of the above are true
  if (this->ReferenceCount == 3 && this->Source != NULL &&
      o != this->Source && this->Source->InRegisterLoop(this) &&
      this->Locator &&
      this->Locator->GetDataSet() == this &&
      this->Locator != o)
    {
    this->SetSource(NULL);
    if (this->Locator)
      {
      this->Locator->SetDataSet(NULL);
      }
    }

  this->vtkObject::UnRegister(o);
}

//----------------------------------------------------------------------------
int vtkPointSet::GetNetReferenceCount()
{
  if (this->Locator && this->Locator->GetDataSet() == this)
    {
    return this->ReferenceCount - 1;
    }
  return this->ReferenceCount;
}

//----------------------------------------------------------------------------
unsigned long vtkPointSet::GetActualMemorySize()
{
  unsigned long size=this->vtkDataSet::GetActualMemorySize();
  if ( this->Points )
    {
    size += this->Points->GetActualMemorySize();
    }
  return size;
}

//----------------------------------------------------------------------------
void vtkPointSet::ShallowCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    this->SetPoints(pointSet->GetPoints());
    }

  // Do superclass
  this->vtkDataSet::ShallowCopy(dataObject);
}

//----------------------------------------------------------------------------
void vtkPointSet::DeepCopy(vtkDataObject *dataObject)
{
  vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject);

  if ( pointSet != NULL )
    {
    if (this->Points == NULL)
      {
      this->Points = vtkPoints::New();
      }
    this->Points->DeepCopy(pointSet->GetPoints());
    }

  // Do superclass
  this->vtkDataSet::DeepCopy(dataObject);
}

//----------------------------------------------------------------------------
void vtkPointSet::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSet::PrintSelf(os,indent);

  os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n";
  os << indent << "Point Coordinates: " << this->Points << "\n";
  os << indent << "Locator: " << this->Locator << "\n";
}

<|endoftext|>