<commit_before>/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2010 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt/ProtocolInfo>

#include <TelepathyQt/ConnectionCapabilities>
#include <TelepathyQt/ConnectionManager>
#include <TelepathyQt/PendingFailure>
#include <TelepathyQt/PendingString>

namespace Tp
{

struct TP_QT_NO_EXPORT ProtocolInfo::Private : public QSharedData
{
    Private()
        : addressingIface(0)
    {
    }

    Private(const ConnectionManagerPtr &cm, const QString &name)
        : cm(cm),
          name(name),
          iconName(QString(QLatin1String("im-%1")).arg(name)),
          addressingIface(0)
    {
    }

    ~Private()
    {
        delete addressingIface;
    }

    Client::ProtocolInterfaceAddressingInterface *addressingInterface()
    {
        if (!addressingIface) {
            ConnectionManagerPtr connectionManager(cm);
            QString escapedProtocolName = name;
            escapedProtocolName.replace(QLatin1Char('-'), QLatin1Char('_'));
            QString protocolPath = QString(
                    QLatin1String("%1/%2"))
                        .arg(connectionManager->objectPath())
                        .arg(escapedProtocolName);
            addressingIface = new Client::ProtocolInterfaceAddressingInterface(
                connectionManager->dbusConnection(),
                connectionManager->busName(), protocolPath);
        }

        return addressingIface;
    }

    WeakPtr<ConnectionManager> cm;
    QString name;
    ProtocolParameterList params;
    ConnectionCapabilities caps;
    QString vcardField;
    QString englishName;
    QString iconName;
    PresenceSpecList statuses;
    AvatarSpec avatarRequirements;
    QStringList addressableVCardFields;
    QStringList addressableUriSchemes;

    Client::ProtocolInterfaceAddressingInterface *addressingIface;
};

/**
 * \class ProtocolInfo
 * \ingroup clientcm
 * \headerfile TelepathyQt/protocol-info.h <TelepathyQt/ProtocolInfo>
 *
 * \brief The ProtocolInfo class represents a Telepathy Protocol.
 */

ProtocolInfo::ProtocolInfo()
{
}

/**
 * Construct a new ProtocolInfo object.
 *
 * \param cm Connection manager owning this ProtocolInfo.
 * \param name Protocol name.
 */
ProtocolInfo::ProtocolInfo(const ConnectionManagerPtr &cm, const QString &name)
    : mPriv(new Private(cm, name))
{
}

ProtocolInfo::ProtocolInfo(const ProtocolInfo &other)
    : mPriv(other.mPriv)
{
}

/**
 * Class destructor.
 */
ProtocolInfo::~ProtocolInfo()
{
}

bool ProtocolInfo::isValid() const
{
    return ((mPriv.constData() != 0) && !(connectionManager().isNull()));
}

ConnectionManagerPtr ProtocolInfo::connectionManager() const
{
    return (mPriv.constData() != 0 ? ConnectionManagerPtr(mPriv->cm) : ConnectionManagerPtr());
}

ProtocolInfo &ProtocolInfo::operator=(const ProtocolInfo &other)
{
    this->mPriv = other.mPriv;
    return *this;
}

/**
 * Return the short name of the connection manager (e.g. "gabble") for this protocol.
 *
 * \return The name of the connection manager for this protocol.
 */
QString ProtocolInfo::cmName() const
{
    if (!isValid()) {
        return QString();
    }

    return connectionManager()->name();
}

/**
 * Return the string identifying this protocol as described in the \telepathy_spec
 * (e.g. "jabber").
 *
 * This identifier is not intended to be displayed to users directly; user
 * interfaces are responsible for mapping them to localized strings.
 *
 * \return A string identifying this protocol.
 */
QString ProtocolInfo::name() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->name;
}

/**
 * Return all supported parameters for this protocol. The parameters' names
 * may either be the well-known strings specified by the \telepathy_spec
 * (e.g. "account" and "password"), or implementation-specific strings.
 *
 * \return A list of parameters for this protocol.
 */
ProtocolParameterList ProtocolInfo::parameters() const
{
    if (!isValid()) {
        return ProtocolParameterList();
    }

    return mPriv->params;
}

/**
 * Return whether a given parameter can be passed to the connection
 * manager when creating a connection to this protocol.
 *
 * \param name The name of a parameter.
 * \return true if the given parameter exists.
 */
bool ProtocolInfo::hasParameter(const QString &name) const
{
    if (!isValid()) {
        return false;
    }

    foreach (const ProtocolParameter &param, mPriv->params) {
        if (param.name() == name) {
            return true;
        }
    }
    return false;
}

/**
 * Return whether it might be possible to register new accounts on this
 * protocol, by setting the special parameter named
 * register to true.
 *
 * \return The same thing as hasParameter("register").
 * \sa hasParameter()
 */
bool ProtocolInfo::canRegister() const
{
    if (!isValid()) {
        return false;
    }

    return hasParameter(QLatin1String("register"));
}

/**
 * Return the capabilities that are expected to be available from a connection
 * to this protocol, i.e. those for which Connection::createChannel() can
 * reasonably be expected to succeed.
 * User interfaces can use this information to show or hide UI components.
 *
 * @return An object representing the capabilities expected to be available from
 *         a connection to this protocol.
 */
ConnectionCapabilities ProtocolInfo::capabilities() const
{
    if (!isValid()) {
        return ConnectionCapabilities();
    }

    return mPriv->caps;
}

/**
 * Return the name of the most common vCard field used for this protocol's
 * contact identifiers, normalized to lower case.
 *
 * One valid use of this field is to answer the question: given a contact's
 * vCard containing an X-JABBER field, how can you communicate with the contact?
 * By iterating through protocols looking for an x-jabber VCardField, one can
 * build up a list of protocols that handle x-jabber, then offer the user a list
 * of accounts for those protocols and/or the option to create a new account for
 * one of those protocols.
 * It is not necessarily valid to interpret contacts' identifiers as values of
 * this vCard field. For instance, telepathy-sofiasip supports contacts whose
 * identifiers are of the form sip:jenny@example.com or tel:8675309, which would
 * not normally both be represented by any single vCard field.
 *
 * \return The most common vCard field used for this protocol's contact
 *         identifiers, or an empty string if there is no such field.
 */
QString ProtocolInfo::vcardField() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->vcardField;
}

/**
 * Return the English-language name of this protocol, such as "AIM" or "Yahoo!".
 *
 * The name can be used as a fallback if an application doesn't have a localized name for this
 * protocol.
 *
 * If the manager file or the CM service doesn't specify the english name, it is inferred from this
 * protocol name, such that for example "google-talk" becomes "Google Talk", but "local-xmpp"
 * becomes "Local Xmpp".
 *
 * \return An English-language name for this protocol.
 */
QString ProtocolInfo::englishName() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->englishName;
}

/**
 * Return the name of an icon for this protocol in the system's icon theme, such as "im-msn".
 *
 * If the manager file or the CM service doesn't specify the icon name, "im-<protocolname>" is
 * assumed.
 *
 * \return The likely name of an icon for this protocol.
 */
QString ProtocolInfo::iconName() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->iconName;
}

/**
 * Return a list of PresenceSpec representing the possible presence statuses
 * from a connection to this protocol.
 *
 * \return A list of PresenceSpec representing the possible presence statuses
 *         from a connection to this protocol.
 */
PresenceSpecList ProtocolInfo::allowedPresenceStatuses() const
{
    if (!isValid()) {
        return PresenceSpecList();
    }

    return mPriv->statuses;
}

/**
 * Return the requirements (size limits, supported MIME types, etc)
 * for avatars used on to this protocol.
 *
 * \return The requirements for avatars used on this protocol.
 */
AvatarSpec ProtocolInfo::avatarRequirements() const
{
    if (!isValid()) {
        return AvatarSpec();
    }

    return mPriv->avatarRequirements;
}

/**
 * Return the vCard fields that can be used to request a contact with on this protocol,
 * normalized to lower case.
 *
 * \return The vCard fields normalized to lower case.
 * \sa addressableUriSchemes()
 */
QStringList ProtocolInfo::addressableVCardFields() const
{
    if (!isValid()) {
        return QStringList();
    }

    return mPriv->addressableVCardFields;
}

/**
 * Return the URI schemes that are supported by this protocol.
 *
 * \return The URI schemes.
 * \sa addressableVCardFields()
 */
QStringList ProtocolInfo::addressableUriSchemes() const
{
    if (!isValid()) {
        return QStringList();
    }

    return mPriv->addressableUriSchemes;
}

/**
 * Attempt to normalize the given \a vcardAddress.
 *
 * An example would be a vCard TEL field with a formatted number in the form of
 * +1 (206) 555 1234, this would be normalized to +12065551234.
 *
 * \param vcardField The vCard field of the address we are normalizing.
 * \param vcardAddress The address to normalize.
 * \return A PendingString which will emit PendingString::finished
 *         when the address has being normalized or an error occurred.
 * \sa normalizeContactUri()
 */
PendingString *ProtocolInfo::normalizeVCardAddress(const QString &vcardField,
        const QString &vcardAddress)
{
    if (!isValid()) {
        return new PendingString(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Protocol object is invalid"));
    }

    Client::ProtocolInterfaceAddressingInterface *iface = mPriv->addressingInterface();
    if (!iface->isValid()) {
        // cm is still valid but no Protocol object found
        return new PendingString(TP_QT_ERROR_NOT_IMPLEMENTED,
                QLatin1String("ConnectionManager does not support Protocol.I.Addressing"));
    }

    return new PendingString(iface->NormalizeVCardAddress(vcardField, vcardAddress),
            connectionManager());
}

/**
 * Attempt to normalize the given contact \a uri.
 *
 * If the URI has extra information beyond what's necessary to identify a particular contact, such
 * as an XMPP resource or an action to carry out, this extra information wil be removed.
 *
 * An example would be xmpp:romeo@Example.Com/Empathy?message;body=Hello, which would be normalized
 * to xmpp:romeo@example.com.
 *
 * \param uri The URI to normalize.
 * \return A PendingString which will emit PendingString::finished
 *         when the \a uri has being normalized or an error occurred.
 * \sa normalizeVCardAddress()
 */
PendingString *ProtocolInfo::normalizeContactUri(const QString &uri)
{
    if (!isValid()) {
        return new PendingString(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Protocol object is invalid"));
    }

    Client::ProtocolInterfaceAddressingInterface *iface = mPriv->addressingInterface();
    if (!iface->isValid()) {
        // cm is still valid but no Protocol object found
        return new PendingString(TP_QT_ERROR_NOT_IMPLEMENTED,
                QLatin1String("ConnectionManager does not support Protocol.I.Addressing"));
    }

    return new PendingString(iface->NormalizeContactURI(uri),
            connectionManager());
}

void ProtocolInfo::addParameter(const ParamSpec &spec)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    QVariant defaultValue;
    if (spec.flags & ConnMgrParamFlagHasDefault) {
        defaultValue = spec.defaultValue.variant();
    }

    uint flags = spec.flags;
    if (spec.name.endsWith(QLatin1String("password"))) {
        flags |= ConnMgrParamFlagSecret;
    }

    ProtocolParameter param(spec.name,
            QDBusSignature(spec.signature),
            defaultValue,
            (ConnMgrParamFlag) flags);
    mPriv->params.append(param);
}

void ProtocolInfo::setVCardField(const QString &vcardField)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->vcardField = vcardField;
}

void ProtocolInfo::setEnglishName(const QString &englishName)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->englishName = englishName;
}

void ProtocolInfo::setIconName(const QString &iconName)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->iconName = iconName;
}

void ProtocolInfo::setRequestableChannelClasses(
        const RequestableChannelClassList &caps)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->caps.updateRequestableChannelClasses(caps);
}

void ProtocolInfo::setAllowedPresenceStatuses(const PresenceSpecList &statuses)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->statuses = statuses;
}

void ProtocolInfo::setAvatarRequirements(const AvatarSpec &avatarRequirements)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->avatarRequirements = avatarRequirements;
}

void ProtocolInfo::setAddressableVCardFields(const QStringList &vcardFields)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->addressableVCardFields = vcardFields;
}

void ProtocolInfo::setAddressableUriSchemes(const QStringList &uriSchemes)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->addressableUriSchemes = uriSchemes;
}

} // Tp
<commit_msg>ProtocolInfo: Fix some small doc issues.<commit_after>/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2010 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt/ProtocolInfo>

#include <TelepathyQt/ConnectionCapabilities>
#include <TelepathyQt/ConnectionManager>
#include <TelepathyQt/PendingFailure>
#include <TelepathyQt/PendingString>

namespace Tp
{

struct TP_QT_NO_EXPORT ProtocolInfo::Private : public QSharedData
{
    Private()
        : addressingIface(0)
    {
    }

    Private(const ConnectionManagerPtr &cm, const QString &name)
        : cm(cm),
          name(name),
          iconName(QString(QLatin1String("im-%1")).arg(name)),
          addressingIface(0)
    {
    }

    ~Private()
    {
        delete addressingIface;
    }

    Client::ProtocolInterfaceAddressingInterface *addressingInterface()
    {
        if (!addressingIface) {
            ConnectionManagerPtr connectionManager(cm);
            QString escapedProtocolName = name;
            escapedProtocolName.replace(QLatin1Char('-'), QLatin1Char('_'));
            QString protocolPath = QString(
                    QLatin1String("%1/%2"))
                        .arg(connectionManager->objectPath())
                        .arg(escapedProtocolName);
            addressingIface = new Client::ProtocolInterfaceAddressingInterface(
                connectionManager->dbusConnection(),
                connectionManager->busName(), protocolPath);
        }

        return addressingIface;
    }

    WeakPtr<ConnectionManager> cm;
    QString name;
    ProtocolParameterList params;
    ConnectionCapabilities caps;
    QString vcardField;
    QString englishName;
    QString iconName;
    PresenceSpecList statuses;
    AvatarSpec avatarRequirements;
    QStringList addressableVCardFields;
    QStringList addressableUriSchemes;

    Client::ProtocolInterfaceAddressingInterface *addressingIface;
};

/**
 * \class ProtocolInfo
 * \ingroup clientcm
 * \headerfile TelepathyQt/protocol-info.h <TelepathyQt/ProtocolInfo>
 *
 * \brief The ProtocolInfo class represents a Telepathy Protocol.
 */

ProtocolInfo::ProtocolInfo()
{
}

/**
 * Construct a new ProtocolInfo object.
 *
 * \param cm Connection manager owning this ProtocolInfo.
 * \param name Protocol name.
 */
ProtocolInfo::ProtocolInfo(const ConnectionManagerPtr &cm, const QString &name)
    : mPriv(new Private(cm, name))
{
}

ProtocolInfo::ProtocolInfo(const ProtocolInfo &other)
    : mPriv(other.mPriv)
{
}

/**
 * Class destructor.
 */
ProtocolInfo::~ProtocolInfo()
{
}

bool ProtocolInfo::isValid() const
{
    return ((mPriv.constData() != 0) && !(connectionManager().isNull()));
}

ConnectionManagerPtr ProtocolInfo::connectionManager() const
{
    return (mPriv.constData() != 0 ? ConnectionManagerPtr(mPriv->cm) : ConnectionManagerPtr());
}

ProtocolInfo &ProtocolInfo::operator=(const ProtocolInfo &other)
{
    this->mPriv = other.mPriv;
    return *this;
}

/**
 * Return the short name of the connection manager (e.g. "gabble") for this protocol.
 *
 * \return The name of the connection manager for this protocol.
 */
QString ProtocolInfo::cmName() const
{
    if (!isValid()) {
        return QString();
    }

    return connectionManager()->name();
}

/**
 * Return the string identifying this protocol as described in the \telepathy_spec
 * (e.g. "jabber").
 *
 * This identifier is not intended to be displayed to users directly; user
 * interfaces are responsible for mapping them to localized strings.
 *
 * \return A string identifying this protocol.
 */
QString ProtocolInfo::name() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->name;
}

/**
 * Return all supported parameters for this protocol. The parameters' names
 * may either be the well-known strings specified by the \telepathy_spec
 * (e.g. "account" and "password"), or implementation-specific strings.
 *
 * \return A list of parameters for this protocol.
 */
ProtocolParameterList ProtocolInfo::parameters() const
{
    if (!isValid()) {
        return ProtocolParameterList();
    }

    return mPriv->params;
}

/**
 * Return whether a given parameter can be passed to the connection
 * manager when creating a connection to this protocol.
 *
 * \param name The name of a parameter.
 * \return true if the given parameter exists.
 */
bool ProtocolInfo::hasParameter(const QString &name) const
{
    if (!isValid()) {
        return false;
    }

    foreach (const ProtocolParameter &param, mPriv->params) {
        if (param.name() == name) {
            return true;
        }
    }
    return false;
}

/**
 * Return whether it might be possible to register new accounts on this
 * protocol, by setting the special parameter named
 * register to true.
 *
 * \return The same thing as hasParameter("register").
 * \sa hasParameter()
 */
bool ProtocolInfo::canRegister() const
{
    if (!isValid()) {
        return false;
    }

    return hasParameter(QLatin1String("register"));
}

/**
 * Return the capabilities that are expected to be available from a connection
 * to this protocol, i.e. those for which Connection::createChannel() can
 * reasonably be expected to succeed.
 * User interfaces can use this information to show or hide UI components.
 *
 * @return An object representing the capabilities expected to be available from
 *         a connection to this protocol.
 */
ConnectionCapabilities ProtocolInfo::capabilities() const
{
    if (!isValid()) {
        return ConnectionCapabilities();
    }

    return mPriv->caps;
}

/**
 * Return the name of the most common vCard field used for this protocol's
 * contact identifiers, normalized to lower case.
 *
 * One valid use of this field is to answer the question: given a contact's
 * vCard containing an X-JABBER field, how can you communicate with the contact?
 * By iterating through protocols looking for an x-jabber VCardField, one can
 * build up a list of protocols that handle x-jabber, then offer the user a list
 * of accounts for those protocols and/or the option to create a new account for
 * one of those protocols.
 * It is not necessarily valid to interpret contacts' identifiers as values of
 * this vCard field. For instance, telepathy-sofiasip supports contacts whose
 * identifiers are of the form sip:jenny@example.com or tel:8675309, which would
 * not normally both be represented by any single vCard field.
 *
 * \return The most common vCard field used for this protocol's contact
 *         identifiers, or an empty string if there is no such field.
 */
QString ProtocolInfo::vcardField() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->vcardField;
}

/**
 * Return the English-language name of this protocol, such as "AIM" or "Yahoo!".
 *
 * The name can be used as a fallback if an application doesn't have a localized name for this
 * protocol.
 *
 * If the manager file or the CM service doesn't specify the english name, it is inferred from this
 * protocol name, such that for example "google-talk" becomes "Google Talk", but "local-xmpp"
 * becomes "Local Xmpp".
 *
 * \return An English-language name for this protocol.
 */
QString ProtocolInfo::englishName() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->englishName;
}

/**
 * Return the name of an icon for this protocol in the system's icon theme, such as "im-msn".
 *
 * If the manager file or the CM service doesn't specify the icon name, "im-<protocolname>" is
 * assumed.
 *
 * \return The likely name of an icon for this protocol.
 */
QString ProtocolInfo::iconName() const
{
    if (!isValid()) {
        return QString();
    }

    return mPriv->iconName;
}

/**
 * Return a list of PresenceSpec representing the possible presence statuses
 * from a connection to this protocol.
 *
 * \return A list of PresenceSpec representing the possible presence statuses
 *         from a connection to this protocol.
 */
PresenceSpecList ProtocolInfo::allowedPresenceStatuses() const
{
    if (!isValid()) {
        return PresenceSpecList();
    }

    return mPriv->statuses;
}

/**
 * Return the requirements (size limits, supported MIME types, etc)
 * for avatars used on to this protocol.
 *
 * \return The requirements for avatars used on this protocol.
 */
AvatarSpec ProtocolInfo::avatarRequirements() const
{
    if (!isValid()) {
        return AvatarSpec();
    }

    return mPriv->avatarRequirements;
}

/**
 * Return the vCard fields that can be used to request a contact with on this protocol,
 * normalized to lower case.
 *
 * \return The vCard fields normalized to lower case.
 * \sa addressableUriSchemes()
 */
QStringList ProtocolInfo::addressableVCardFields() const
{
    if (!isValid()) {
        return QStringList();
    }

    return mPriv->addressableVCardFields;
}

/**
 * Return the URI schemes that are supported by this protocol.
 *
 * \return The URI schemes.
 * \sa addressableVCardFields()
 */
QStringList ProtocolInfo::addressableUriSchemes() const
{
    if (!isValid()) {
        return QStringList();
    }

    return mPriv->addressableUriSchemes;
}

/**
 * Attempt to normalize the given \a vcardAddress.
 *
 * For example, a vCard TEL field with a formatted number in the form of
 * +1 (206) 555 1234, could be normalized to +12065551234.
 *
 * \param vcardField The vCard field the \a vcardAddress belongs to.
 * \param vcardAddress The address to normalize.
 * \return A PendingString which will emit PendingString::finished
 *         when the address has been normalized or an error occurred.
 * \sa normalizeContactUri()
 */
PendingString *ProtocolInfo::normalizeVCardAddress(const QString &vcardField,
        const QString &vcardAddress)
{
    if (!isValid()) {
        return new PendingString(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Protocol object is invalid"));
    }

    Client::ProtocolInterfaceAddressingInterface *iface = mPriv->addressingInterface();
    if (!iface->isValid()) {
        // cm is still valid but no Protocol object found
        return new PendingString(TP_QT_ERROR_NOT_IMPLEMENTED,
                QLatin1String("ConnectionManager does not support Protocol.I.Addressing"));
    }

    return new PendingString(iface->NormalizeVCardAddress(vcardField, vcardAddress),
            connectionManager());
}

/**
 * Attempt to normalize the given contact \a uri.
 *
 * If the URI has extra information beyond what's necessary to identify a particular contact, such
 * as an XMPP resource or an action to carry out, this extra information wil be removed.
 *
 * An example would be xmpp:romeo@Example.Com/Empathy?message;body=Hello, which would be normalized
 * to xmpp:romeo@example.com.
 *
 * \param uri The URI to normalize.
 * \return A PendingString which will emit PendingString::finished
 *         when the \a uri has been normalized or an error occurred.
 * \sa normalizeVCardAddress()
 */
PendingString *ProtocolInfo::normalizeContactUri(const QString &uri)
{
    if (!isValid()) {
        return new PendingString(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Protocol object is invalid"));
    }

    Client::ProtocolInterfaceAddressingInterface *iface = mPriv->addressingInterface();
    if (!iface->isValid()) {
        // cm is still valid but no Protocol object found
        return new PendingString(TP_QT_ERROR_NOT_IMPLEMENTED,
                QLatin1String("ConnectionManager does not support Protocol.I.Addressing"));
    }

    return new PendingString(iface->NormalizeContactURI(uri),
            connectionManager());
}

void ProtocolInfo::addParameter(const ParamSpec &spec)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    QVariant defaultValue;
    if (spec.flags & ConnMgrParamFlagHasDefault) {
        defaultValue = spec.defaultValue.variant();
    }

    uint flags = spec.flags;
    if (spec.name.endsWith(QLatin1String("password"))) {
        flags |= ConnMgrParamFlagSecret;
    }

    ProtocolParameter param(spec.name,
            QDBusSignature(spec.signature),
            defaultValue,
            (ConnMgrParamFlag) flags);
    mPriv->params.append(param);
}

void ProtocolInfo::setVCardField(const QString &vcardField)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->vcardField = vcardField;
}

void ProtocolInfo::setEnglishName(const QString &englishName)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->englishName = englishName;
}

void ProtocolInfo::setIconName(const QString &iconName)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->iconName = iconName;
}

void ProtocolInfo::setRequestableChannelClasses(
        const RequestableChannelClassList &caps)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->caps.updateRequestableChannelClasses(caps);
}

void ProtocolInfo::setAllowedPresenceStatuses(const PresenceSpecList &statuses)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->statuses = statuses;
}

void ProtocolInfo::setAvatarRequirements(const AvatarSpec &avatarRequirements)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->avatarRequirements = avatarRequirements;
}

void ProtocolInfo::setAddressableVCardFields(const QStringList &vcardFields)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->addressableVCardFields = vcardFields;
}

void ProtocolInfo::setAddressableUriSchemes(const QStringList &uriSchemes)
{
    if (!isValid()) {
        mPriv = new Private;
    }

    mPriv->addressableUriSchemes = uriSchemes;
}

} // Tp
<|endoftext|>


<commit_before>//
// Name:	 app.cpp
// Purpose:  Example GLUT/vtlib application.
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "SDL.h"
#ifdef __FreeBSD__
#  include <ieeefp.h>
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"

class App
{
public:
	bool CreateScene();

	void videosettings(bool same_video_mode, bool fullscreen);
	void display();
	void run();
	int main();
	void process_mouse_button(const SDL_Event &event);
	void process_mouse_motion(const SDL_Event &event);
	void process_event(const SDL_Event &event);
	void process_events();
};

//
// Initialize the SDL display.  This code originated from another project,
// so i am not sure of the details, but it should work well on each
// platform.
//
void App::videosettings(bool same_video_mode, bool fullscreen)
{
	int width, height;

	if ( ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) == -1 ) )
	{
		std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl;
		exit( -1 );
	}
	atexit( SDL_Quit );

	SDL_VideoInfo const * info = SDL_GetVideoInfo();
	if( !info )
	{
		std::cerr << "Video query failed: " << SDL_GetError( ) << std::endl;
		exit( -1 );
	}

	int num_modes;
	SDL_Rect ** modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
	if ( (modes != NULL) && (modes != (SDL_Rect **)-1) )
	{
		for (num_modes = 0; modes[num_modes]; num_modes++);
		if ( same_video_mode )
		{
			// EEERRR should get the surface and use its parameters
			width = modes[0]->w;
			height = modes[0]->h;
		}
		else
		{
			for ( int i=num_modes-1; i >= 0; i-- )
			{
				width = modes[i]->w;
				height = modes[i]->h;
				if ( (modes[i]->w >= 1024) && (modes[i]->h >= 768) ) {
					break;
				}
			}
		}
	}
	else
	{
		std::cerr << "Video list modes failed: " << SDL_GetError( ) << std::endl;
		exit( -1 );
	}

	std::cerr << width << " " << height << std::endl;
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	int flags = SDL_OPENGL | SDL_DOUBLEBUF;

	if (fullscreen)
		flags |= SDL_FULLSCREEN;
	if ( info->hw_available )
		flags |= SDL_HWSURFACE;
	else
		flags |= SDL_SWSURFACE;

	if ( info->blit_hw )
		flags |= SDL_HWACCEL;

	if( SDL_SetVideoMode( width, height, 16, flags ) == 0 )
	{
		std::cerr << "Video mode set failed: " << SDL_GetError( ) << std::endl;
		exit( -1 );
	}
	// Tell the SDL output size to vtlib
	vtGetScene()->SetWindowSize(width, height);
}

//--------------------------------------------------------------------------

//
// Create the 3d scene: call vtlib to load the terrain and prepare for
// user interaction.
//
bool App::CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Set the global data path
	StringArray paths;
	paths.Append(new vtString("Data/"));
	vtTerrain::SetDataPath(paths);

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(100000);

	// Create a new terrain scene.  This will contain all the terrain
	// that are created.
	vtTerrainScene *ts = new vtTerrainScene();
	vtRoot *pTopGroup = ts->BeginTerrainScene(false);

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its paramters from a file
	vtTerrain *pTerr = new vtTerrain();
	pTerr->SetParamFile("Data/Simple.ini");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	int iError;
	if (!pTerr->CreateScene(false, iError))
	{
		printf("Terrain creation failed.");
		return false;
	}
	ts->Finish(paths);
	ts->SetTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Flight speed is 400 m/frame
	// Height over terrain is 100 m
	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(400, 100, true);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	return true;
}

void App::display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	vtGetScene()->DoUpdate();

	glFinish();
	SDL_GL_SwapBuffers();
}

void App::process_mouse_button(const SDL_Event &sdle)
{
	// turn SDL mouse button event into a VT mouse event
	vtMouseEvent event;
	event.type = (sdle.button.type == SDL_MOUSEBUTTONDOWN) ? VT_DOWN : VT_UP;

	if (sdle.button.button == 1)
		event.button = VT_LEFT;
	else if (sdle.button.button == 2)
		event.button = VT_MIDDLE;
	else if (sdle.button.button == 3)
		event.button = VT_RIGHT;

	event.flags = 0;
	event.pos.Set(sdle.button.x, sdle.button.y);

	vtGetScene()->OnMouse(event);
}

void App::process_mouse_motion(const SDL_Event &sdle)
{
	// turn SDL mouse move event into a VT mouse event
	vtMouseEvent event;
	event.type = VT_MOVE;
	event.button = VT_NONE;
	event.flags = 0;
	event.pos.Set(sdle.motion.x, sdle.motion.y);

	vtGetScene()->OnMouse(event);
}

void App::process_event(const SDL_Event &event)
{
	int key;

	switch( event.type )
	{
		case SDL_QUIT:
			exit(0);
		case SDL_KEYDOWN:
			break;
		case SDL_KEYUP:
			// turn SDL key event into a VT mouse event
			key = event.key.keysym.sym;
			if ( key == 27 /* ESC */ || key == 'q' || key == 'Q' )
				exit(0);
			vtGetScene()->OnKey(key, 0);
			break;
		case SDL_MOUSEMOTION:
			process_mouse_motion(event);
			break;
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			process_mouse_button(event);
			break;
		case SDL_VIDEORESIZE:
			// Tell vtlib
			vtGetScene()->SetWindowSize(event.resize.w, event.resize.h);
			break;
	}
}

void App::process_events()
{
	SDL_Event event;

	while ( SDL_PollEvent( &event ) )
		process_event(event);
}

void App::run()
{
	while ( true )
	{
		display();			// draw scene
		process_events();	// handle user events
	}
}

/*
  The works.
*/
int App::main()
{
#ifdef __FreeBSD__
	/*  FreeBSD is more stringent with FP ops by default, and OSG is	*/
	/*	doing silly things sqrt(Inf) (computing lengths of MAXFLOAT		*/
	/*	and NaN Vec3's).   This turns off FP bug core dumps, ignoring	*/
	/*	the error like most platforms do by default.					*/
	fpsetmask(0);
#endif
	printf("Initializing SDL..\n");
	videosettings(true, false);

	printf("Creating the terrain..\n");
	if (!CreateScene())
		return 0;

	printf("Running..\n");
	run();

	return 0;
}

int main(int, char ** )
{
	App app;
	return app.main();
}
<commit_msg>begin PSM support<commit_after>//
// Name:	 app.cpp
// Purpose:  Example GLUT/vtlib application.
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "SDL.h"
#ifdef __FreeBSD__
#  include <ieeefp.h>
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"

class App
{
public:
	bool CreateScene();

	void videosettings(bool same_video_mode, bool fullscreen);
	void display();
	void run();
	int main();
	void process_mouse_button(const SDL_Event &event);
	void process_mouse_motion(const SDL_Event &event);
	void process_event(const SDL_Event &event);
	void process_events();
};

//
// Initialize the SDL display.  This code originated from another project,
// so i am not sure of the details, but it should work well on each
// platform.
//
void App::videosettings(bool same_video_mode, bool fullscreen)
{
	int width, height;

	if ( ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) == -1 ) )
	{
		std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl;
		exit( -1 );
	}
	atexit( SDL_Quit );

	SDL_VideoInfo const * info = SDL_GetVideoInfo();
	if( !info )
	{
		std::cerr << "Video query failed: " << SDL_GetError( ) << std::endl;
		exit( -1 );
	}

	int num_modes;
	SDL_Rect ** modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
	if ( (modes != NULL) && (modes != (SDL_Rect **)-1) )
	{
		for (num_modes = 0; modes[num_modes]; num_modes++);
		if ( same_video_mode )
		{
			// EEERRR should get the surface and use its parameters
			width = modes[0]->w;
			height = modes[0]->h;
		}
		else
		{
			for ( int i=num_modes-1; i >= 0; i-- )
			{
				width = modes[i]->w;
				height = modes[i]->h;
				if ( (modes[i]->w >= 1024) && (modes[i]->h >= 768) ) {
					break;
				}
			}
		}
	}
	else
	{
		std::cerr << "Video list modes failed: " << SDL_GetError( ) << std::endl;
		exit( -1 );
	}

	std::cerr << width << " " << height << std::endl;
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	int flags = SDL_OPENGL | SDL_DOUBLEBUF;

	if (fullscreen)
		flags |= SDL_FULLSCREEN;
	if ( info->hw_available )
		flags |= SDL_HWSURFACE;
	else
		flags |= SDL_SWSURFACE;

	if ( info->blit_hw )
		flags |= SDL_HWACCEL;

	if( SDL_SetVideoMode( width, height, 16, flags ) == 0 )
	{
		std::cerr << "Video mode set failed: " << SDL_GetError( ) << std::endl;
		exit( -1 );
	}
	// Tell the SDL output size to vtlib
	vtGetScene()->SetWindowSize(width, height);
}

//--------------------------------------------------------------------------

//
// Create the 3d scene: call vtlib to load the terrain and prepare for
// user interaction.
//
bool App::CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Set the global data path
	StringArray paths;
	paths.Append(new vtString("Data/"));
	vtTerrain::SetDataPath(paths);

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(100000);

	// Create a new terrain scene.  This will contain all the terrain
	// that are created.
	vtTerrainScene *ts = new vtTerrainScene();
	vtRoot *pTopGroup = ts->BeginTerrainScene(false);

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its paramters from a file
	vtTerrain *pTerr = new vtTerrain();
	pTerr->SetParamFile("Data/Simple.ini");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	int iError;
	if (!pTerr->CreateScene(false, iError))
	{
		printf("Terrain creation failed.");
		return false;
	}
	ts->Finish(paths);
	ts->SetTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Flight speed is 400 m/frame
	// Height over terrain is 100 m
	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(400, 100, true);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	return true;
}

void App::display()
{
#if !VTLIB_PSM
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	vtGetScene()->DoUpdate();

	SDL_GL_SwapBuffers();
#endif
}

void App::process_mouse_button(const SDL_Event &sdle)
{
	// turn SDL mouse button event into a VT mouse event
	vtMouseEvent event;
	event.type = (sdle.button.type == SDL_MOUSEBUTTONDOWN) ? VT_DOWN : VT_UP;

	if (sdle.button.button == 1)
		event.button = VT_LEFT;
	else if (sdle.button.button == 2)
		event.button = VT_MIDDLE;
	else if (sdle.button.button == 3)
		event.button = VT_RIGHT;

	event.flags = 0;
	event.pos.Set(sdle.button.x, sdle.button.y);

	vtGetScene()->OnMouse(event);
}

void App::process_mouse_motion(const SDL_Event &sdle)
{
	// turn SDL mouse move event into a VT mouse event
	vtMouseEvent event;
	event.type = VT_MOVE;
	event.button = VT_NONE;
	event.flags = 0;
	event.pos.Set(sdle.motion.x, sdle.motion.y);

	vtGetScene()->OnMouse(event);
}

void App::process_event(const SDL_Event &event)
{
	int key;

	switch( event.type )
	{
		case SDL_QUIT:
			exit(0);
		case SDL_KEYDOWN:
			break;
		case SDL_KEYUP:
			// turn SDL key event into a VT mouse event
			key = event.key.keysym.sym;
			if ( key == 27 /* ESC */ || key == 'q' || key == 'Q' )
				exit(0);
			vtGetScene()->OnKey(key, 0);
			break;
		case SDL_MOUSEMOTION:
			process_mouse_motion(event);
			break;
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			process_mouse_button(event);
			break;
		case SDL_VIDEORESIZE:
			// Tell vtlib
			vtGetScene()->SetWindowSize(event.resize.w, event.resize.h);
			break;
	}
}

void App::process_events()
{
	SDL_Event event;

	while ( SDL_PollEvent( &event ) )
		process_event(event);
}

void App::run()
{
	while ( true )
	{
		display();			// draw scene
		process_events();	// handle user events
	}
}

/*
  The works.
*/
int App::main()
{
#ifdef __FreeBSD__
	/*  FreeBSD is more stringent with FP ops by default, and OSG is	*/
	/*	doing silly things sqrt(Inf) (computing lengths of MAXFLOAT		*/
	/*	and NaN Vec3's).   This turns off FP bug core dumps, ignoring	*/
	/*	the error like most platforms do by default.					*/
	fpsetmask(0);
#endif
	printf("Initializing SDL..\n");
	videosettings(true, false);

	printf("Creating the terrain..\n");
	if (!CreateScene())
		return 0;

	printf("Running..\n");
	run();

	return 0;
}

int main(int, char ** )
{
	App app;
	return app.main();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#include "scene.h"
#include <glm/gtc/matrix_transform.hpp>
namespace strat
{
  namespace gfx
  {
    glm::mat4 const& Scene::projection_matrix() const noexcept
    {
      return projection_;
    }
    void Scene::projection_matrix(glm::mat4 const& p) noexcept
    {
      if(p != projection_)
      {
        for(auto obs : observers_)
        {
          obs->set_projection(p);
        }
        projection_ = p;
      }
    }

    glm::mat4 const& Scene::view_matrix() const noexcept
    {
      return view_;
    }
    void Scene::view_matrix(glm::mat4 const& v) noexcept
    {
      if(v != view_)
      {
        for(auto obs : observers_)
        {
          obs->set_view(v);
        }
        view_ = v;
      }
    }
    void Scene::on_observer_add_(IScene_Observer* obs) const noexcept
    {
      // Set both the projection and view matrix on the scene.
      obs->set_projection(projection_);
      obs->set_view(view_);
    }

    Scene make_isometric_scene() noexcept
    {
      auto ret = Scene{};
      ret.projection_matrix(glm::ortho(-10.0, 10.0, -10.0, 10.0, 0.1, 100.0));
      ret.view_matrix(glm::lookAt(glm::vec3(-5.0, 10, -5.0),
                                  glm::vec3(0.0, 0.0, 0.0),
                                  glm::vec3(0.0, 1.0, 0.0)));
      return ret;
    }
  }
}
<commit_msg>We shouldn't be totally reversed in our camera position.<commit_after>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#include "scene.h"
#include <glm/gtc/matrix_transform.hpp>
namespace strat
{
  namespace gfx
  {
    glm::mat4 const& Scene::projection_matrix() const noexcept
    {
      return projection_;
    }
    void Scene::projection_matrix(glm::mat4 const& p) noexcept
    {
      if(p != projection_)
      {
        for(auto obs : observers_)
        {
          obs->set_projection(p);
        }
        projection_ = p;
      }
    }

    glm::mat4 const& Scene::view_matrix() const noexcept
    {
      return view_;
    }
    void Scene::view_matrix(glm::mat4 const& v) noexcept
    {
      if(v != view_)
      {
        for(auto obs : observers_)
        {
          obs->set_view(v);
        }
        view_ = v;
      }
    }
    void Scene::on_observer_add_(IScene_Observer* obs) const noexcept
    {
      // Set both the projection and view matrix on the scene.
      obs->set_projection(projection_);
      obs->set_view(view_);
    }

    Scene make_isometric_scene() noexcept
    {
      auto ret = Scene{};
      ret.projection_matrix(glm::ortho(-10.0, 10.0, -10.0, 10.0, 0.1, 100.0));
      ret.view_matrix(glm::lookAt(glm::vec3(5.0, 10, 5.0),
                                  glm::vec3(0.0, 0.0, 0.0),
                                  glm::vec3(0.0, 1.0, 0.0)));
      return ret;
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>psuedo code for new renderer system.<commit_after><|endoftext|>


<commit_before>/**
 * @file
 */
#include "bi/expression/LocalVariable.hpp"

#include "bi/visitor/all.hpp"

bi::LocalVariable::LocalVariable(const Annotation annotation, Name* name,
    Type* type, Expression* brackets, Expression* args, Expression* value,
    Location* loc) :
    Annotated(annotation),
    Expression(type, loc),
    Named(name),
    Bracketed(brackets),
    Argumented(args),
    Valued(value) {
  //
}

bi::LocalVariable::~LocalVariable() {
  //
}

bool bi::LocalVariable::needsConstruction() const {
  return !args->isEmpty()
      || (value->isEmpty() && (!type->isArray() || !brackets->isEmpty()));
}

bi::Expression* bi::LocalVariable::accept(Cloner* visitor) const {
  return visitor->clone(this);
}

bi::Expression* bi::LocalVariable::accept(Modifier* visitor) {
  return visitor->modify(this);
}

void bi::LocalVariable::accept(Visitor* visitor) const {
  visitor->visit(this);
}
<commit_msg>Fixed compile warning.<commit_after>/**
 * @file
 */
#include "bi/expression/LocalVariable.hpp"

#include "bi/visitor/all.hpp"

bi::LocalVariable::LocalVariable(const Annotation annotation, Name* name,
    Type* type, Expression* brackets, Expression* args, Expression* value,
    Location* loc) :
    Expression(type, loc),
    Annotated(annotation),
    Named(name),
    Bracketed(brackets),
    Argumented(args),
    Valued(value) {
  //
}

bi::LocalVariable::~LocalVariable() {
  //
}

bool bi::LocalVariable::needsConstruction() const {
  return !args->isEmpty()
      || (value->isEmpty() && (!type->isArray() || !brackets->isEmpty()));
}

bi::Expression* bi::LocalVariable::accept(Cloner* visitor) const {
  return visitor->clone(this);
}

bi::Expression* bi::LocalVariable::accept(Modifier* visitor) {
  return visitor->modify(this);
}

void bi::LocalVariable::accept(Visitor* visitor) const {
  visitor->visit(this);
}
<|endoftext|>


<commit_before>//
//
// MIT License
//
// Copyright (c) 2017 Stellacore Corporation.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//

/*! \file
\brief  This file contains unit test for dat::quantum
*/

#include "libdat/quantum.h"

#include "libdat/compare.h"
#include "libdat/info.h"
#include "libdat/validity.h"
#include "libio/stream.h"

#include <iostream>
#include <sstream>
#include <string>

namespace
{

//! Check for common functions
std::string
dat_quantum_test0
	()
{
	std::ostringstream oss;
	/*
	dat::quantum const aNull(dat::nullValue<dat::quantum>());
	if (dat::isValid(aNull))
	{
		oss << "Failure of null value test" << std::endl;
		oss << "infoString: " << dat::infoString(aNull) << std::endl;
	}
	*/
	return oss.str();
}

	//! Generate test cases for specified types (need to support negatives)
	template <typename BaseType, typename DataType>
	void
	runTest
		( std::ostream & oss
		, std::string const & name
		)
	{
		using FracType = DataType;
		dat::quantum::Splitter<BaseType, FracType> const quantizer{ 7 };
		using FloorResid = std::pair<BaseType, FracType>;
		std::vector<std::pair<DataType, FloorResid> > const valExpPairs
			{ {  9, {  1, 2 } }
			, {  3, {  0, 3 } }
			, {  0, {  0, 0 } }
			, { -3, { -1, 4 } }
			, { -9, { -2, 5 } }
			};

		for (std::pair<DataType, FloorResid> const & valExpPair : valExpPairs)
		{
			DataType const & value = valExpPair.first;
			FloorResid const & expFR = valExpPair.second;
			FloorResid const gotFR{ quantizer(value) };
			if (! dat::nearlyEquals(gotFR, expFR))
			{
				oss << "Failure of quantizer test: " << name << std::endl;
				oss << dat::infoString(expFR, "expFR") << std::endl;
				oss << dat::infoString(gotFR, "gotFR") << std::endl;
			}
		}
	}

//! Check quantization functor
std::string
dat_quantum_test1
	()
{
	std::ostringstream oss;

	runTest<int, int>(oss, "int,int");
	runTest<int, float>(oss, "int,float");
	runTest<double, int>(oss, "double,int");
	runTest<double, float>(oss, "double,float");

	return oss.str();
}

}

//! Unit test for dat::quantum
int
main
	( int const /*argc*/
	, char const * const * /*argv*/
	)
{
	std::ostringstream oss;

	// run tests
	oss << dat_quantum_test0();
	oss << dat_quantum_test1();

	// check/report results
	std::string const errMessages(oss.str());
	if (! errMessages.empty())
	{
		io::err() << errMessages << std::endl;
		return 1;
	}
	return 0;
}
<commit_msg>testdat/uquantum.cpp added Splitter test for fractional delta<commit_after>//
//
// MIT License
//
// Copyright (c) 2017 Stellacore Corporation.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//

/*! \file
\brief  This file contains unit test for dat::quantum
*/

#include "libdat/quantum.h"

#include "libdat/compare.h"
#include "libdat/info.h"
#include "libdat/validity.h"
#include "libio/stream.h"

#include <iostream>
#include <sstream>
#include <string>

namespace
{

//! Check for common functions
std::string
dat_quantum_test0
	()
{
	std::ostringstream oss;
	/*
	dat::quantum const aNull(dat::nullValue<dat::quantum>());
	if (dat::isValid(aNull))
	{
		oss << "Failure of null value test" << std::endl;
		oss << "infoString: " << dat::infoString(aNull) << std::endl;
	}
	*/

	// check general convention
	dat::quantum::Splitter<long, double> const split{ .25 };
	std::pair<long, double> const expPos{ 3L*4L + 3L, 0. };
	std::pair<long, double> const gotPos{ split(3.75) };
	if (! dat::nearlyEquals(gotPos, expPos))
	{
		oss << "Failure of fractional delta positive value test" << std::endl;
		oss << dat::infoString(expPos, "expPos") << std::endl;
		oss << dat::infoString(gotPos, "gotPos") << std::endl;
	}

	std::pair<long, double> const expNeg{ -4L*4L + 1L, 0. };
	std::pair<long, double> const gotNeg{ split(-3.75) };
	if (! dat::nearlyEquals(gotNeg, expNeg))
	{
		oss << "Failure of fractional delta negative value test" << std::endl;
		oss << dat::infoString(expNeg, "expNeg") << std::endl;
		oss << dat::infoString(gotNeg, "gotNeg") << std::endl;
	}

	return oss.str();
}

	//! Generate test cases for specified types (need to support negatives)
	template <typename BaseType, typename DataType>
	void
	runTest
		( std::ostream & oss
		, std::string const & name
		)
	{
		using FracType = DataType;
		dat::quantum::Splitter<BaseType, FracType> const quantizer{ 7 };
		using FloorResid = std::pair<BaseType, FracType>;
		std::vector<std::pair<DataType, FloorResid> > const valExpPairs
			{ {  9, {  1, 2 } }
			, {  3, {  0, 3 } }
			, {  0, {  0, 0 } }
			, { -3, { -1, 4 } }
			, { -9, { -2, 5 } }
			};

		for (std::pair<DataType, FloorResid> const & valExpPair : valExpPairs)
		{
			DataType const & value = valExpPair.first;
			FloorResid const & expFR = valExpPair.second;
			FloorResid const gotFR{ quantizer(value) };
			if (! dat::nearlyEquals(gotFR, expFR))
			{
				oss << "Failure of quantizer test: " << name << std::endl;
				oss << dat::infoString(expFR, "expFR") << std::endl;
				oss << dat::infoString(gotFR, "gotFR") << std::endl;
			}
		}
	}

//! Check quantization functor
std::string
dat_quantum_test1
	()
{
	std::ostringstream oss;

	runTest<int, int>(oss, "int,int");
	runTest<int, float>(oss, "int,float");
	runTest<double, int>(oss, "double,int");
	runTest<double, float>(oss, "double,float");

	return oss.str();
}

}

//! Unit test for dat::quantum
int
main
	( int const /*argc*/
	, char const * const * /*argv*/
	)
{
	std::ostringstream oss;

	// run tests
	oss << dat_quantum_test0();
	oss << dat_quantum_test1();

	// check/report results
	std::string const errMessages(oss.str());
	if (! errMessages.empty())
	{
		io::err() << errMessages << std::endl;
		return 1;
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "Controller.h"
#include <iostream>

Controller::Controller():
	my_serial(port, baud, serial::Timeout::simpleTimeout(timeOut))
{
	sigmaRef = 0.0;
	psiRef = 0.0;

	JRigidInv << 0, 0,
				 0, 0;

	xip(0) = 0.0;
	xip(1) = 0.0;

	qpRef = JRigidInv*xip;

	psipRef = qpRef(0);
	sigmapRef = qpRef(1);

	H = 1 / 2 * pow(0.0, 2) + g*sin(beta)*0.0;
	Href = getReferenceEnergy();
	Htilde = H - Href;

	this->init();

}

// Controller::Controller(double x, double z, double xp, double zp)
// {
	//JRigidInv.resize(2, 2);
	//xip.resize(2, 1);
	//qpRef.resize(2, 1);

	//sigmaRef = sqrt(-pow(r, 2) + pow(ox - x, 2) + pow(oz - z, 2));
	//psiRef = atan2((oz - z)*sigmaRef + r*(x - ox), (x - ox)*sigmaRef + r*(z - oz));

	//JRigidInv(0,0) = (ox*r - r*x + sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2))*(-oz + z)) /
	//	((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	//JRigidInv(0, 1) = (oz*r + (ox - x)*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)) - r*z) /
	//	((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	//JRigidInv(1, 0) = (-ox + x) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));

	//JRigidInv(1,1) = (-oz + z) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));

	//xip(0) = xp;
	//xip(1) = zp;

	//qpRef = JRigidInv*xip;

	//psipRef = qpRef(0);
	//sigmapRef = qpRef(1);

	//H = 1 / 2 * pow(zp, 2) + g*sin(beta)*z;
	//Href = getReferenceEnergy();
	//Htilde = H - Href;

//}

Controller::~Controller()
{

}

void Controller::init()
{
// create a motor object

//std::cout << "Main Thread :: ID = " << std::this_thread::get_id() << std::endl;

int motorSetPosition = 0;
//std::cout << "In Main Thread : Before Thread Start motorSetPosition = " << motorSetPosition << std::endl;

std::cout << "Start Motor Thread" << std::endl;
// ToDo: get a handle on that thread
std::thread threadObj(&MotorDriver::motor_control_thread_function, &this->motorObj, std::ref(motorSetPosition));
if (threadObj.joinable())
{
	//threadObj.join();
	//std::cout << "Joined Thread " << std::endl;
	std::cout << "Detaching Thread " << std::endl;
	threadObj.detach();
}

//// port, baudrate, timeout in milliseconds
//my_serial.setBaudrate(baud);
//my_serial.setPort(port);
//my_serial.setTimeout(serial::Timeout::max(), timeOut, 0, timeOut, 0);

cout << "Is the serial port open?";
if (my_serial.isOpen())
cout << " Yes." << endl;
else
cout << " No." << endl;

//std::cout << "In Main Thread : After Thread Joins motorSetPosition = " << motorSetPosition << std::endl;

}
Vector2d Controller::getBallPosition()
{
	return Vector2d(x, z);
}

void Controller::setBallPosition(double a, double b)
{
	x = a;
	z = b;
}

Vector2d Controller::getBallVelocity()
{
	return Vector2d(xp, zp);
}

void Controller::setBallVelocity(double a, double b)
{
	xp = a;
	zp = b;
}

double Controller::getReferenceEnergy()
{
	return Href;
}

void Controller::setReferenceEnergy(double referenceEnergy)
{
	Href = referenceEnergy;
}

double Controller::computeVerticalEnergy()
{
	return 1 / 2 * pow(zp, 2) + g*sin(beta)*z;
}

void Controller::computeJacobianInverse()
{
	JRigidInv(0, 0) = (ox*r - r*x + sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2))*(-oz + z)) /
		((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	JRigidInv(0, 1) = (oz*r + (ox - x)*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)) - r*z) /
		((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	JRigidInv(1, 0) = (-ox + x) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));

	JRigidInv(1, 1) = (-oz + z) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));
}

void Controller::updateReferencePosition()
{
	sigmaRef = sqrt(-pow(r, 2) + pow(ox - x, 2) + pow(oz - z, 2));
	psiRef = atan2((oz - z)*sigmaRef + r*(x - ox), (x - ox)*sigmaRef + r*(z - oz));
}

void Controller::updateReferenceVelocity()
{
	computeJacobianInverse();
	Vector2d xip(xp, zp);
	Vector2d refVel = JRigidInv*xip;

	psipRef = refVel(0);
	sigmapRef = refVel(1);
}

double Controller::computeDesiredPaddlePosition()
{
	double rhoBar = ox;
	double rhoRef = 0.0;
	double rhopRef = 0.0;

	H = computeVerticalEnergy();
	Htilde = H - Href;

	updateReferencePosition();
	updateReferenceVelocity();

	rhoRef = sigmaRef*cos(psiRef);
	rhopRef = sigmapRef*cos(psiRef) - sigmapRef*psipRef*sin(psiRef);

	return  -(kappa0 + kappa1*Htilde)*psiRef + kappa00*(rhoRef - rhoBar) + kappa01*rhopRef;
}

void Controller::controlArm()
{

	/**********************************************/
	/* Insert motor control commands from here on */

	// Get the Current Position
	//motor.getPosition(pPosition);		// Read Motor Position

	double TargetPositionRad = this->computeDesiredPaddlePosition();		// Need conversion to ticks or something here.

																		// std::cout << "I'm commanding " << TargetPositionRad << "[rad] to the motor.\n";

																		//	while (!pTargetReached)
																		//	{
																		//motor.getPositionRad(&pPositionRad);		// Read Motor Position

																		//motor.moveToPositionRad(TargetPositionRad, Absolute, Immediately);

																		//motor.getMovementState(&pTargetReached, &pErrorCode);

	motorObj.setDesiredMotorPosition(TargetPositionRad);

	sentNumber.floatingPoint = 90.12f;
	uint8_t endMessage = 0x0A;					//New Line Character in Hex.
	size_t bytes_wrote;
	size_t bytes_read = 0;

	//for (int count = 0; count < 1000; count++) {
		bytes_wrote = my_serial.write(sentNumber.binary, FLOATSIZE);
		//my_serial.write(&endMessage, 1);

		//bytes_read = my_serial.read(incomingData, FLOATSIZE);

		// for (int i = 1; i < FLOATSIZE; i++)
			// receivedNumber.binary[i] = incomingData[i];

		//cout << "Iteration: " << count << ", Bytes written: ";
		//cout << bytes_wrote << ", What is sent: " << sentNumber.floatingPoint << ", Bytes read: ";
		//cout << bytes_read << ", What is read: " << receivedNumber.floatingPoint << endl;
	//}

	//std::cout << "Exiting commandMotor(double, double, double, double)\n";

	//	}
	/* End of motor commands */
	/*************************/
}
<commit_msg>write and read serial in controller<commit_after>#include "Controller.h"
#include <iostream>

Controller::Controller():
	my_serial(port, baud, serial::Timeout::simpleTimeout(timeOut))
{
	sigmaRef = 0.0;
	psiRef = 0.0;

	JRigidInv << 0, 0,
				 0, 0;

	xip(0) = 0.0;
	xip(1) = 0.0;

	qpRef = JRigidInv*xip;

	psipRef = qpRef(0);
	sigmapRef = qpRef(1);

	H = 1 / 2 * pow(0.0, 2) + g*sin(beta)*0.0;
	Href = getReferenceEnergy();
	Htilde = H - Href;

	this->init();

}

// Controller::Controller(double x, double z, double xp, double zp)
// {
	//JRigidInv.resize(2, 2);
	//xip.resize(2, 1);
	//qpRef.resize(2, 1);

	//sigmaRef = sqrt(-pow(r, 2) + pow(ox - x, 2) + pow(oz - z, 2));
	//psiRef = atan2((oz - z)*sigmaRef + r*(x - ox), (x - ox)*sigmaRef + r*(z - oz));

	//JRigidInv(0,0) = (ox*r - r*x + sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2))*(-oz + z)) /
	//	((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	//JRigidInv(0, 1) = (oz*r + (ox - x)*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)) - r*z) /
	//	((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	//JRigidInv(1, 0) = (-ox + x) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));

	//JRigidInv(1,1) = (-oz + z) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));

	//xip(0) = xp;
	//xip(1) = zp;

	//qpRef = JRigidInv*xip;

	//psipRef = qpRef(0);
	//sigmapRef = qpRef(1);

	//H = 1 / 2 * pow(zp, 2) + g*sin(beta)*z;
	//Href = getReferenceEnergy();
	//Htilde = H - Href;

//}

Controller::~Controller()
{

}

void Controller::init()
{
// create a motor object

std::cout << "Controller Init, Thread :: ID = " << std::this_thread::get_id() << std::endl;

int motorSetPosition = 0;
//std::cout << "In Main Thread : Before Thread Start motorSetPosition = " << motorSetPosition << std::endl;

std::cout << "Start Motor Thread" << std::endl;
// ToDo: get a handle on that thread
std::thread threadObj(&MotorDriver::motor_control_thread_function, &this->motorObj, std::ref(motorSetPosition));
if (threadObj.joinable())
{
	//threadObj.join();
	//std::cout << "Joined Thread " << std::endl;
	std::cout << "Detaching Thread " << std::endl;
	threadObj.detach();
}

//// port, baudrate, timeout in milliseconds
//my_serial.setBaudrate(baud);
//my_serial.setPort(port);
//my_serial.setTimeout(serial::Timeout::max(), timeOut, 0, timeOut, 0);

cout << "Is the serial port open?";
if (my_serial.isOpen())
cout << " Yes." << endl;
else
cout << " No." << endl;

//std::cout << "In Main Thread : After Thread Joins motorSetPosition = " << motorSetPosition << std::endl;

}
Vector2d Controller::getBallPosition()
{
	return Vector2d(x, z);
}

void Controller::setBallPosition(double a, double b)
{
	x = a;
	z = b;
}

Vector2d Controller::getBallVelocity()
{
	return Vector2d(xp, zp);
}

void Controller::setBallVelocity(double a, double b)
{
	xp = a;
	zp = b;
}

double Controller::getReferenceEnergy()
{
	return Href;
}

void Controller::setReferenceEnergy(double referenceEnergy)
{
	Href = referenceEnergy;
}

double Controller::computeVerticalEnergy()
{
	return 1 / 2 * pow(zp, 2) + g*sin(beta)*z;
}

void Controller::computeJacobianInverse()
{
	JRigidInv(0, 0) = (ox*r - r*x + sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2))*(-oz + z)) /
		((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	JRigidInv(0, 1) = (oz*r + (ox - x)*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)) - r*z) /
		((pow(ox - x, 2) + pow(oz - z, 2))*sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2)));

	JRigidInv(1, 0) = (-ox + x) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));

	JRigidInv(1, 1) = (-oz + z) / sqrt(pow(ox, 2) - pow(r, 2) - 2 * ox*x + pow(x, 2) + pow(oz - z, 2));
}

void Controller::updateReferencePosition()
{
	sigmaRef = sqrt(-pow(r, 2) + pow(ox - x, 2) + pow(oz - z, 2));
	psiRef = atan2((oz - z)*sigmaRef + r*(x - ox), (x - ox)*sigmaRef + r*(z - oz));
}

void Controller::updateReferenceVelocity()
{
	computeJacobianInverse();
	Vector2d xip(xp, zp);
	Vector2d refVel = JRigidInv*xip;

	psipRef = refVel(0);
	sigmapRef = refVel(1);
}

double Controller::computeDesiredPaddlePosition()
{
	double rhoBar = ox;
	double rhoRef = 0.0;
	double rhopRef = 0.0;

	H = computeVerticalEnergy();
	Htilde = H - Href;

	updateReferencePosition();
	updateReferenceVelocity();

	rhoRef = sigmaRef*cos(psiRef);
	rhopRef = sigmapRef*cos(psiRef) - sigmapRef*psipRef*sin(psiRef);

	return  -(kappa0 + kappa1*Htilde)*psiRef + kappa00*(rhoRef - rhoBar) + kappa01*rhopRef;
}

void Controller::controlArm()
{

	/**********************************************/
	/* Insert motor control commands from here on */

	// Get the Current Position
	//motor.getPosition(pPosition);		// Read Motor Position

	double TargetPositionRad = this->computeDesiredPaddlePosition();		// Need conversion to ticks or something here.

																		// std::cout << "I'm commanding " << TargetPositionRad << "[rad] to the motor.\n";

																		//	while (!pTargetReached)
																		//	{
																		//motor.getPositionRad(&pPositionRad);		// Read Motor Position

																		//motor.moveToPositionRad(TargetPositionRad, Absolute, Immediately);

																		//motor.getMovementState(&pTargetReached, &pErrorCode);

	motorObj.setDesiredMotorPosition(TargetPositionRad);

	sentNumber.floatingPoint = 90.12f;
	uint8_t endMessage = 0x0A;					//New Line Character in Hex.
	size_t bytes_wrote;
	size_t bytes_read = 0;

	//for (int count = 0; count < 1000; count++) {
		bytes_wrote = my_serial.write(sentNumber.binary, FLOATSIZE);
		my_serial.write(&endMessage, 1);

		bytes_read = my_serial.read(incomingData, FLOATSIZE);

		 for (int i = 1; i < FLOATSIZE; i++)
			receivedNumber.binary[i] = incomingData[i];

		cout << "Bytes written: ";
		cout << bytes_wrote << ", What is sent: " << sentNumber.floatingPoint << ", Bytes read: ";
		cout << bytes_read << ", What is read: " << receivedNumber.floatingPoint << endl;
	//}

	//std::cout << "Exiting commandMotor(double, double, double, double)\n";

	//	}
	/* End of motor commands */
	/*************************/
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <exception>
#include    <malloc.h>

#if     qPlatform_POSIX
#include    <unistd.h>
#endif

#include    "../Memory/Common.h"

#include    "MallocGuard.h"

using   namespace   Stroika::Foundation;
using   Memory::Byte;

#if     qStroika_Foundation_Debug_MallocGuard
namespace {
    using   GuradBytes_ =   Byte[16];
    constexpr   GuradBytes_ kMallocGuardHeader_ =   { 0xf3, 0xfa, 0x0b, 0x93, 0x48, 0x50, 0x46, 0xe6, 0x22, 0xf1, 0xfa, 0xc0, 0x9a, 0x0b, 0xeb, 0x23, };
    constexpr   GuradBytes_ kMallocGuardFooter_ =   { 0x07, 0x41, 0xa4, 0x2b, 0xba, 0x97, 0xcb, 0x38, 0x46, 0x1e, 0x3c, 0x42, 0x3c, 0x5f, 0x0c, 0x80, };
    constexpr   Byte        kDeadMansLand_[]    =   { 0x1d, 0xb6, 0x20, 0x27, 0x43, 0x7a, 0x3d, 0x1a, 0x13, 0x65, };

    // need header with size, so we can ....
    struct alignas(alignof(long double))  HeaderOrFooter_ {
        GuradBytes_ fGuard;
        size_t      fRequestedBlockSize;
    };

    void    OhShit_ ()
    {
        static  bool    sDone_      { false };      // doing terminate MIGHT allocate more memory ... just go with the flow if that happens - and dont re-barf (e.g. allow backtrace if possible)
        if (not sDone_) {
            sDone_ = true;
            const char  kMsg_[] =   "Fatal Error detected in Stroika Malloc Guard\n";
            ::write (2, kMsg_, NEltsOf (kMsg_));
            std::terminate ();
        }
    }

    void*   ExposedPtrToBackendPtr_ (void* p)
    {
        if (p == nullptr) {
            OhShit_ ();
        }
        return reinterpret_cast<HeaderOrFooter_*> (p) - 1;
    }
    void*   BackendPtrToExposedPtr_ (void* p)
    {
        if (p == nullptr) {
            OhShit_ ();
        }
        return reinterpret_cast<HeaderOrFooter_*> (p) + 1;
    }
    size_t  AdjustMallocSize_ (size_t s)
    {
        return s + 2 * sizeof (HeaderOrFooter_);
    }

    bool    IsDeadMansLand_ (const Byte* s, const Byte* e)
    {
        return false;
    }
    void    SetDeadMansLand_ (Byte* s, Byte* e)
    {
        const   Byte*   pBadFillStart   =   begin (kDeadMansLand_);
        const   Byte*   pBadFillEnd     =   end (kDeadMansLand_);
        const   Byte*   badFillI        =   pBadFillStart;
        for (Byte* oi = s; oi != e; ++oi) {
            *oi = *badFillI;
            badFillI++;
            if (badFillI == pBadFillEnd) {
                badFillI = pBadFillStart;
            }
        }
    }
    void    SetDeadMansLand_ (void* p)
    {
        const HeaderOrFooter_*  hp  =   reinterpret_cast<const HeaderOrFooter_*> (p);
        SetDeadMansLand_ (reinterpret_cast<Byte*> (p), reinterpret_cast<Byte*> (p) + AdjustMallocSize_ (hp->fRequestedBlockSize));
    }

    /*
     *  not 100% threadsafe, but OK.
     *
     *  Also FreeList alway uses BackendPtr - not ExternalPtr
     */
    void*   sFreeList_[100];
    void**  sFreeList_NextFreeI_    =   &sFreeList_[0];
    void    Add2FreeList_ (void* p)
    {
        *sFreeList_NextFreeI_ = p;
        void**  next = sFreeList_NextFreeI_ + 1;
        if (next >= end (sFreeList_)) {
            next = begin (sFreeList_);
        }
        sFreeList_NextFreeI_ = next;    // race in that we could SKIP recording a free element, but thats harmless - just a missed opportunity to detect an error
    }
    void    ClearFromFreeList_ (void* p)
    {
        // not a race because you cannot free and allocate the same pointer at the same time
        for (void** i = begin (sFreeList_); i != end (sFreeList_); ++i) {
            if (*i == p) {
                *i = nullptr;
            }
        }
    }
    bool    IsInFreeList_ (const void* p)
    {
        for (void** i = begin (sFreeList_); i != end (sFreeList_); ++i) {
            if (*i == p) {
                return true;
            }
        }
        return false;
    }

    void    Validate_ (const HeaderOrFooter_& header, const HeaderOrFooter_& footer)
    {
        if (::memcmp (&header.fGuard, &kMallocGuardHeader_, sizeof (kMallocGuardHeader_)) != 0) {
            OhShit_ ();
        }
        if (::memcmp (&footer.fGuard, &kMallocGuardFooter_, sizeof (kMallocGuardFooter_)) != 0) {
            OhShit_ ();
        }
        if (header.fRequestedBlockSize != footer.fRequestedBlockSize) {
            OhShit_ ();
        }
        // OK
    }
    void    ValidateBackendPtr_ (const void* p)
    {
        const HeaderOrFooter_*  hp  =   reinterpret_cast<const HeaderOrFooter_*> (p);
        const HeaderOrFooter_*  fp  =   reinterpret_cast<const HeaderOrFooter_*> (reinterpret_cast<const Byte*> (hp + 1) + hp->fRequestedBlockSize);
        HeaderOrFooter_ footer;
        (void)::memcpy (&footer, fp, sizeof (footer));  // align access
        Validate_ (*hp, footer);
        if (IsInFreeList_ (p)) {
            OhShit_ ();
        }
    }
    void   PatchNewPointer_ (void* p, size_t requestedSize)
    {
        HeaderOrFooter_*  hp   =   reinterpret_cast< HeaderOrFooter_*> (p);
        (void)::memcpy (begin (hp->fGuard), begin (kMallocGuardHeader_),  NEltsOf (kMallocGuardHeader_));
        hp->fRequestedBlockSize = requestedSize;
        HeaderOrFooter_*  fp  =    reinterpret_cast< HeaderOrFooter_*> (reinterpret_cast<Byte*> (hp + 1) + hp->fRequestedBlockSize);
        (void)::memcpy (begin (fp->fGuard), begin (kMallocGuardFooter_),  NEltsOf (kMallocGuardFooter_));
        fp->fRequestedBlockSize = requestedSize;
    }
}
#endif

#if     qStroika_Foundation_Debug_MallocGuard

extern "C"  void    __libc_free (void* __ptr);
extern "C"  void*   __libc_malloc (size_t __size);
extern "C"  void*   __libc_realloc (void* __ptr, size_t __size);
extern "C"  void*   __libc_calloc (size_t __nmemb, size_t __size);
extern "C"  void    __libc_free (void* __ptr);

extern "C"  void*   calloc (size_t __nmemb, size_t __size)
{
    size_t  n   =   __nmemb * __size;
    void*   p   =   malloc (n);
    (void)::memset (p, 0, n);
    return p;
}

extern "C"  void    cfree (void* __ptr)
{
    free (__ptr);
}

extern "C"  void    free (void* __ptr)
{
    if (__ptr == nullptr) {
        // according to http://linux.die.net/man/3/free
        // "if ptr is NULL, no operation is performed." - and glibc does call this internally
        return;
    }
    void*   p = ExposedPtrToBackendPtr_ (__ptr);
    ValidateBackendPtr_ (p);
    SetDeadMansLand_ (p);
    Add2FreeList_ (p);
    __libc_free (p);
}

extern "C"  void*   malloc (size_t __size)
{
    void*   p   =   __libc_malloc (AdjustMallocSize_ (__size));
    PatchNewPointer_ (p, __size);
    ClearFromFreeList_ (p);
    ValidateBackendPtr_ (p);
    if (p != nullptr) {
        p = BackendPtrToExposedPtr_ (p);
    }
    return p;
}

extern "C"  void*    realloc (void* __ptr, size_t __size)
{
    if (__ptr == nullptr) {
        // from http://linux.die.net/man/3/realloc
        // If ptr is NULL, then the call is equivalent to malloc(size),
        return malloc (__size);
    }
    if (__ptr != nullptr and __size == 0) {
        // from http://linux.die.net/man/3/realloc
        // if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr).
        free (__ptr);
        return nullptr;
    }
    void*   p   =   ExposedPtrToBackendPtr_ (__ptr);
    ValidateBackendPtr_ (p);
    size_t  n   =   AdjustMallocSize_ (__size);
    void*   newP = __libc_realloc (p, n);
    if (newP != nullptr) {
        PatchNewPointer_ (newP, __size);
        if (newP != p) {
            //Already been freed, so not safe to set at this point!!! - SetDeadMansLand_ (p);
            Add2FreeList_ (p);
            ClearFromFreeList_ (newP);
        }
        ValidateBackendPtr_ (newP);
        newP = BackendPtrToExposedPtr_ (newP);
    }
    return newP;
}

extern "C"  void*   valloc (size_t __size)
{
    // http://linux.die.net/man/3/valloc "OBSOLETE"
    OhShit_ ();
    return nullptr;
}

extern "C"  void*   pvalloc (size_t __size)
{
    // http://linux.die.net/man/3/valloc "OBSOLETE"
    OhShit_ ();
    return nullptr;
}

extern "C"  void*   memalign (size_t __alignment, size_t __size)
{
    // http://linux.die.net/man/3/valloc "OBSOLETE"
    OhShit_ ();
    return nullptr;
}

extern "C"  size_t malloc_usable_size (void* ptr)
{
    if (ptr == nullptr) {
        return 0;
    }
    void*   p   =   ExposedPtrToBackendPtr_ (ptr);
    ValidateBackendPtr_ (p);
    const HeaderOrFooter_*  hp  =   reinterpret_cast<const HeaderOrFooter_*> (p);
    return hp->fRequestedBlockSize;
}

extern "C"  int posix_memalign (void** memptr, size_t alignment, size_t size)
{
    // Probably SHOULD implement ... but so far not running into trouble cuz anything I link to calling this...
    OhShit_ ();
    return 0;
}
#endif
<commit_msg>cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <exception>
#include    <malloc.h>

#if     qPlatform_POSIX
#include    <unistd.h>
#endif

#include    "../Memory/Common.h"

#include    "MallocGuard.h"

using   namespace   Stroika::Foundation;
using   Memory::Byte;

#if     qStroika_Foundation_Debug_MallocGuard
namespace {
    using   GuradBytes_ =   Byte[16];
    constexpr   GuradBytes_ kMallocGuardHeader_ =   { 0xf3, 0xfa, 0x0b, 0x93, 0x48, 0x50, 0x46, 0xe6, 0x22, 0xf1, 0xfa, 0xc0, 0x9a, 0x0b, 0xeb, 0x23, };
    constexpr   GuradBytes_ kMallocGuardFooter_ =   { 0x07, 0x41, 0xa4, 0x2b, 0xba, 0x97, 0xcb, 0x38, 0x46, 0x1e, 0x3c, 0x42, 0x3c, 0x5f, 0x0c, 0x80, };
    constexpr   Byte        kDeadMansLand_[]    =   { 0x1d, 0xb6, 0x20, 0x27, 0x43, 0x7a, 0x3d, 0x1a, 0x13, 0x65, };

    struct alignas(alignof(long double))  HeaderOrFooter_ {
        GuradBytes_ fGuard;
        size_t      fRequestedBlockSize;
    };

    void    OhShit_ ()
    {
        static  bool    sDone_      { false };      // doing terminate MIGHT allocate more memory ... just go with the flow if that happens - and dont re-barf (e.g. allow backtrace if possible)
        if (not sDone_) {
            sDone_ = true;
            const char  kMsg_[] =   "Fatal Error detected in Stroika Malloc Guard\n";
            ::write (2, kMsg_, NEltsOf (kMsg_));
            std::terminate ();
        }
    }

    void*   ExposedPtrToBackendPtr_ (void* p)
    {
        if (p == nullptr) {
            OhShit_ ();
        }
        return reinterpret_cast<HeaderOrFooter_*> (p) - 1;
    }
    void*   BackendPtrToExposedPtr_ (void* p)
    {
        if (p == nullptr) {
            OhShit_ ();
        }
        return reinterpret_cast<HeaderOrFooter_*> (p) + 1;
    }
    size_t  AdjustMallocSize_ (size_t s)
    {
        return s + 2 * sizeof (HeaderOrFooter_);
    }

    bool    IsDeadMansLand_ (const Byte* s, const Byte* e)
    {
        return false;
    }
    void    SetDeadMansLand_ (Byte* s, Byte* e)
    {
        const   Byte*   pBadFillStart   =   begin (kDeadMansLand_);
        const   Byte*   pBadFillEnd     =   end (kDeadMansLand_);
        const   Byte*   badFillI        =   pBadFillStart;
        for (Byte* oi = s; oi != e; ++oi) {
            *oi = *badFillI;
            badFillI++;
            if (badFillI == pBadFillEnd) {
                badFillI = pBadFillStart;
            }
        }
    }
    void    SetDeadMansLand_ (void* p)
    {
        const HeaderOrFooter_*  hp  =   reinterpret_cast<const HeaderOrFooter_*> (p);
        SetDeadMansLand_ (reinterpret_cast<Byte*> (p), reinterpret_cast<Byte*> (p) + AdjustMallocSize_ (hp->fRequestedBlockSize));
    }

    /*
     *  not 100% threadsafe, but OK.
     *
     *  Also FreeList alway uses BackendPtr - not ExternalPtr
     */
    void*   sFreeList_[100];
    void**  sFreeList_NextFreeI_    =   &sFreeList_[0];
    void    Add2FreeList_ (void* p)
    {
        *sFreeList_NextFreeI_ = p;
        void**  next = sFreeList_NextFreeI_ + 1;
        if (next >= end (sFreeList_)) {
            next = begin (sFreeList_);
        }
        sFreeList_NextFreeI_ = next;    // race in that we could SKIP recording a free element, but thats harmless - just a missed opportunity to detect an error
    }
    void    ClearFromFreeList_ (void* p)
    {
        // not a race because you cannot free and allocate the same pointer at the same time
        for (void** i = begin (sFreeList_); i != end (sFreeList_); ++i) {
            if (*i == p) {
                *i = nullptr;
            }
        }
    }
    bool    IsInFreeList_ (const void* p)
    {
        for (void** i = begin (sFreeList_); i != end (sFreeList_); ++i) {
            if (*i == p) {
                return true;
            }
        }
        return false;
    }

    void    Validate_ (const HeaderOrFooter_& header, const HeaderOrFooter_& footer)
    {
        if (::memcmp (&header.fGuard, &kMallocGuardHeader_, sizeof (kMallocGuardHeader_)) != 0) {
            OhShit_ ();
        }
        if (::memcmp (&footer.fGuard, &kMallocGuardFooter_, sizeof (kMallocGuardFooter_)) != 0) {
            OhShit_ ();
        }
        if (header.fRequestedBlockSize != footer.fRequestedBlockSize) {
            OhShit_ ();
        }
        // OK
    }
    void    ValidateBackendPtr_ (const void* p)
    {
        const HeaderOrFooter_*  hp  =   reinterpret_cast<const HeaderOrFooter_*> (p);
        const HeaderOrFooter_*  fp  =   reinterpret_cast<const HeaderOrFooter_*> (reinterpret_cast<const Byte*> (hp + 1) + hp->fRequestedBlockSize);
        HeaderOrFooter_ footer;
        (void)::memcpy (&footer, fp, sizeof (footer));  // align access
        Validate_ (*hp, footer);
        if (IsInFreeList_ (p)) {
            OhShit_ ();
        }
    }

    void   PatchNewPointer_ (void* p, size_t requestedSize)
    {
        HeaderOrFooter_*  hp   =   reinterpret_cast< HeaderOrFooter_*> (p);
        (void)::memcpy (begin (hp->fGuard), begin (kMallocGuardHeader_),  NEltsOf (kMallocGuardHeader_));
        hp->fRequestedBlockSize = requestedSize;
        HeaderOrFooter_*  fp  =    reinterpret_cast< HeaderOrFooter_*> (reinterpret_cast<Byte*> (hp + 1) + hp->fRequestedBlockSize);
        (void)::memcpy (begin (fp->fGuard), begin (kMallocGuardFooter_),  NEltsOf (kMallocGuardFooter_));
        fp->fRequestedBlockSize = requestedSize;
    }
}
#endif

#if     qStroika_Foundation_Debug_MallocGuard

extern "C"  void    __libc_free (void* __ptr);
extern "C"  void*   __libc_malloc (size_t __size);
extern "C"  void*   __libc_realloc (void* __ptr, size_t __size);
extern "C"  void*   __libc_calloc (size_t __nmemb, size_t __size);
extern "C"  void    __libc_free (void* __ptr);

extern "C"  void*   calloc (size_t __nmemb, size_t __size)
{
    size_t  n   =   __nmemb * __size;
    void*   p   =   malloc (n);
    (void)::memset (p, 0, n);
    return p;
}

extern "C"  void    cfree (void* __ptr)
{
    free (__ptr);
}

extern "C"  void    free (void* __ptr)
{
    if (__ptr == nullptr) {
        // according to http://linux.die.net/man/3/free
        // "if ptr is NULL, no operation is performed." - and glibc does call this internally
        return;
    }
    void*   p = ExposedPtrToBackendPtr_ (__ptr);
    ValidateBackendPtr_ (p);
    SetDeadMansLand_ (p);
    Add2FreeList_ (p);
    __libc_free (p);
}

extern "C"  void*   malloc (size_t __size)
{
    void*   p   =   __libc_malloc (AdjustMallocSize_ (__size));
    PatchNewPointer_ (p, __size);
    ClearFromFreeList_ (p);
    ValidateBackendPtr_ (p);
    if (p != nullptr) {
        p = BackendPtrToExposedPtr_ (p);
    }
    return p;
}

extern "C"  void*    realloc (void* __ptr, size_t __size)
{
    if (__ptr == nullptr) {
        // from http://linux.die.net/man/3/realloc
        // If ptr is NULL, then the call is equivalent to malloc(size),
        return malloc (__size);
    }
    if (__ptr != nullptr and __size == 0) {
        // from http://linux.die.net/man/3/realloc
        // if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr).
        free (__ptr);
        return nullptr;
    }
    void*   p   =   ExposedPtrToBackendPtr_ (__ptr);
    ValidateBackendPtr_ (p);
    size_t  n   =   AdjustMallocSize_ (__size);
    void*   newP = __libc_realloc (p, n);
    if (newP != nullptr) {
        PatchNewPointer_ (newP, __size);
        if (newP != p) {
            //Already been freed, so not safe to set at this point!!! - SetDeadMansLand_ (p);
            Add2FreeList_ (p);
            ClearFromFreeList_ (newP);
        }
        ValidateBackendPtr_ (newP);
        newP = BackendPtrToExposedPtr_ (newP);
    }
    return newP;
}

extern "C"  void*   valloc (size_t __size)
{
    // http://linux.die.net/man/3/valloc "OBSOLETE"
    OhShit_ ();
    return nullptr;
}

extern "C"  void*   pvalloc (size_t __size)
{
    // http://linux.die.net/man/3/valloc "OBSOLETE"
    OhShit_ ();
    return nullptr;
}

extern "C"  void*   memalign (size_t __alignment, size_t __size)
{
    // http://linux.die.net/man/3/valloc "OBSOLETE"
    OhShit_ ();
    return nullptr;
}

extern "C"  size_t malloc_usable_size (void* ptr)
{
    if (ptr == nullptr) {
        return 0;
    }
    void*   p   =   ExposedPtrToBackendPtr_ (ptr);
    ValidateBackendPtr_ (p);
    const HeaderOrFooter_*  hp  =   reinterpret_cast<const HeaderOrFooter_*> (p);
    return hp->fRequestedBlockSize;
}

extern "C"  int posix_memalign (void** memptr, size_t alignment, size_t size)
{
    // Probably SHOULD implement ... but so far not running into trouble cuz anything I link to calling this...
    OhShit_ ();
    return 0;
}
#endif
<|endoftext|>