<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "factory.h"
#include "factory_p.h"

#include "backendinterface.h"
#include "medianode_p.h"
#include "audiooutput.h"
#include "audiooutput_p.h"
#include "globalstatic_p.h"
#include "platformplugin.h"
#include "phononnamespace_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QLibrary>
#include <QtCore/QList>
#include <QtCore/QPluginLoader>
#include <QtDBus/QtDBus>
#include <QtGui/QIcon>

namespace Phonon
{

PHONON_GLOBAL_STATIC(Phonon::FactoryPrivate, globalFactory)

void Factory::setBackend(QObject *b)
{
    Q_ASSERT(globalFactory->m_backendObject == 0);
    globalFactory->m_backendObject = b;
}

/*void Factory::createBackend(const QString &library, const QString &version)
{
    Q_ASSERT(globalFactory->m_backendObject == 0);
    PlatformPlugin *f = globalFactory->platformPlugin();
    if (f) {
        globalFactory->m_backendObject = f->createBackend(library, version);
    }
}*/

bool FactoryPrivate::createBackend()
{
    Q_ASSERT(m_backendObject == 0);
    PlatformPlugin *f = globalFactory->platformPlugin();
    if (f) {
        m_backendObject = f->createBackend();
    }
    if (!m_backendObject) {
        // could not load a backend through the platform plugin. Falling back to the default.
#if defined(Q_WS_MAC)
        const QLatin1String pluginName("mac_qt7");
#elif defined(Q_WS_WIN)
#if defined(QT_NO_DEBUG)
        const QLatin1String pluginName("phonon_ds9");
#else
        const QLatin1String pluginName("phonon_ds9d");
#endif
#else
        const QLatin1String pluginName("xine");
#endif
        const QLatin1String suffix("/phonon_backend/");
        foreach (QString libPath, QCoreApplication::libraryPaths()) {
            libPath += suffix;
            const QDir dir(libPath);
            if (!dir.exists()) {
                pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist";
                continue;
            }
            QLibrary pluginLib(libPath + pluginName);
            if (pluginLib.load()) {
                pDebug() << Q_FUNC_INFO << "trying to load " << pluginLib.fileName();
                QPluginLoader pluginLoader(pluginLib.fileName());
                Q_ASSERT(pluginLoader.load());
                pDebug() << pluginLoader.instance();
                m_backendObject = pluginLoader.instance();
                if (m_backendObject) {
                    break;
                }
            }
        }
        if (!m_backendObject) {
            pDebug() << Q_FUNC_INFO << "phonon plugin could not be loaded:" << pluginName;
            return false;
        }
    }

    connect(m_backendObject, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
            SLOT(objectDescriptionChanged(ObjectDescriptionType)));

    return true;
}

FactoryPrivate::FactoryPrivate()
    : m_backendObject(0),
    m_platformPlugin(0),
    m_noPlatformPlugin(false)
{
    // Add the post routine to make sure that all other global statics (especially the ones from Qt)
    // are still available. If the FactoryPrivate dtor is called too late many bad things can happen
    // as the whole backend might still be alive.
    qAddPostRoutine(globalFactory.destroy);
#ifndef QT_NO_DBUS
    QDBusConnection::sessionBus().connect(QString(), QString(), "org.kde.Phonon.Factory",
            "phononBackendChanged", this, SLOT(phononBackendChanged()));
#endif
}

FactoryPrivate::~FactoryPrivate()
{
    foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
        bp->deleteBackendObject();
    }
    if (objects.size() > 0) {
        pError() << "The backend objects are not deleted as was requested.";
        qDeleteAll(objects);
    }
    delete m_backendObject;
    delete m_platformPlugin;
}

void FactoryPrivate::objectDescriptionChanged(ObjectDescriptionType type)
{
#ifdef PHONON_METHODTEST
    Q_UNUSED(type);
#else
    pDebug() << Q_FUNC_INFO << type;
    switch (type) {
    case AudioOutputDeviceType:
        emit availableAudioOutputDevicesChanged();
        break;
    default:
        break;
    }
    //emit capabilitiesChanged();
#endif // PHONON_METHODTEST
}

Factory::Sender *Factory::sender()
{
    return globalFactory;
}

bool Factory::isMimeTypeAvailable(const QString &mimeType)
{
    PlatformPlugin *f = globalFactory->platformPlugin();
    if (f) {
        return f->isMimeTypeAvailable(mimeType);
    }
    return true; // the MIME type might be supported, let BackendCapabilities find out
}

void Factory::registerFrontendObject(MediaNodePrivate *bp)
{
    globalFactory->mediaNodePrivateList.prepend(bp); // inserted last => deleted first
}

void Factory::deregisterFrontendObject(MediaNodePrivate *bp)
{
    // The Factory can already be cleaned up while there are other frontend objects still alive.
    // When those are deleted they'll call deregisterFrontendObject through ~BasePrivate
    if (!globalFactory.isDestroyed()) {
        globalFactory->mediaNodePrivateList.removeAll(bp);
    }
}

void FactoryPrivate::phononBackendChanged()
{
    if (m_backendObject) {
        foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
            bp->deleteBackendObject();
        }
        if (objects.size() > 0) {
            pDebug() << "WARNING: we were asked to change the backend but the application did\n"
                "not free all references to objects created by the factory. Therefore we can not\n"
                "change the backend without crashing. Now we have to wait for a restart to make\n"
                "backendswitching possible.";
            // in case there were objects deleted give 'em a chance to recreate
            // them now
            foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
                bp->createBackendObject();
            }
            return;
        }
        delete m_backendObject;
        m_backendObject = 0;
    }
    createBackend();
    foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
        bp->createBackendObject();
    }
    emit backendChanged();
}

//X void Factory::freeSoundcardDevices()
//X {
//X     if (globalFactory->backend) {
//X         globalFactory->backend->freeSoundcardDevices();
//X     }
//X }

void FactoryPrivate::objectDestroyed(QObject * obj)
{
    //pDebug() << Q_FUNC_INFO << obj;
    objects.removeAll(obj);
}

#define FACTORY_IMPL(classname) \
QObject *Factory::create ## classname(QObject *parent) \
{ \
    if (backend()) { \
        return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent)); \
    } \
    return 0; \
}
#define FACTORY_IMPL_1ARG(classname) \
QObject *Factory::create ## classname(int arg1, QObject *parent) \
{ \
    if (backend()) { \
        return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent, QList<QVariant>() << arg1)); \
    } \
    return 0; \
}

FACTORY_IMPL(MediaObject)
FACTORY_IMPL_1ARG(Effect)
FACTORY_IMPL(VolumeFaderEffect)
FACTORY_IMPL(AudioOutput)
FACTORY_IMPL(AudioDataOutput)
FACTORY_IMPL(Visualization)
FACTORY_IMPL(VideoDataOutput)
FACTORY_IMPL(VideoWidget)

#undef FACTORY_IMPL

PlatformPlugin *FactoryPrivate::platformPlugin()
{
    if (!m_platformPlugin) {
        if (m_noPlatformPlugin) {
            return 0;
        }
#ifndef QT_NO_DBUS
        if (!QCoreApplication::instance() || QCoreApplication::applicationName().isEmpty()) {
            pWarning() << "Phonon needs QCoreApplication::applicationName to be set to export audio output names through the DBUS interface";
        }
#endif
        const QString suffix(QLatin1String("/phonon_platform"));
        Q_ASSERT(QCoreApplication::instance());
        foreach (QString libPath, QCoreApplication::libraryPaths()) {
            libPath += suffix;
            const QDir dir(libPath);
            if (!dir.exists()) {
                pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist";
                continue;
            }
            QLibrary pluginLib(libPath + QLatin1String("/kde"));
            if (pluginLib.load()) {
                pDebug() << Q_FUNC_INFO << "trying to load " << pluginLib.fileName();
                QPluginLoader pluginLoader(pluginLib.fileName());
                Q_ASSERT_X(pluginLoader.load(), Q_FUNC_INFO,
                           qPrintable(pluginLoader.errorString()));
                pDebug() << pluginLoader.instance();
                m_platformPlugin = qobject_cast<PlatformPlugin *>(pluginLoader.instance());
                pDebug() << m_platformPlugin;
                if (m_platformPlugin) {
                    return m_platformPlugin;
                }
            } else {
                pDebug() << Q_FUNC_INFO << dir.absolutePath() << "exists but the KDE platform plugin was not loadable:" << pluginLib.errorString();
            }
        }
        if (!m_platformPlugin) {
            pDebug() << Q_FUNC_INFO << "phonon_platform/kde plugin could not be loaded";
            m_noPlatformPlugin = true;
        }
    }
    return m_platformPlugin;
}

PlatformPlugin *Factory::platformPlugin()
{
    return globalFactory->platformPlugin();
}

QObject *Factory::backend(bool createWhenNull)
{
    if (globalFactory.isDestroyed()) {
        return 0;
    }
    if (createWhenNull && globalFactory->m_backendObject == 0) {
        globalFactory->createBackend();
        // XXX: might create "reentrancy" problems:
        // a method calls this method and is called again because the
        // backendChanged signal is emitted
        emit globalFactory->backendChanged();
    }
    return globalFactory->m_backendObject;
}

#define GET_STRING_PROPERTY(name) \
QString Factory::name() \
{ \
    if (globalFactory->m_backendObject) { \
        return globalFactory->m_backendObject->property(#name).toString(); \
    } \
    return QString(); \
} \

GET_STRING_PROPERTY(identifier)
GET_STRING_PROPERTY(backendName)
GET_STRING_PROPERTY(backendComment)
GET_STRING_PROPERTY(backendVersion)
GET_STRING_PROPERTY(backendIcon)
GET_STRING_PROPERTY(backendWebsite)

QObject *Factory::registerQObject(QObject *o)
{
    if (o) {
        QObject::connect(o, SIGNAL(destroyed(QObject *)), globalFactory, SLOT(objectDestroyed(QObject *)), Qt::DirectConnection);
        globalFactory->objects.append(o);
    }
    return o;
}

} //namespace Phonon

#include "moc_factory.cpp"
#include "moc_factory_p.cpp"

// vim: sw=4 ts=4
<commit_msg>Don't abort when a backend plugin fails to load, but print out a useful debug message instead.<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "factory.h"
#include "factory_p.h"

#include "backendinterface.h"
#include "medianode_p.h"
#include "audiooutput.h"
#include "audiooutput_p.h"
#include "globalstatic_p.h"
#include "platformplugin.h"
#include "phononnamespace_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QLibrary>
#include <QtCore/QList>
#include <QtCore/QPluginLoader>
#include <QtDBus/QtDBus>
#include <QtGui/QIcon>

namespace Phonon
{

PHONON_GLOBAL_STATIC(Phonon::FactoryPrivate, globalFactory)

void Factory::setBackend(QObject *b)
{
    Q_ASSERT(globalFactory->m_backendObject == 0);
    globalFactory->m_backendObject = b;
}

/*void Factory::createBackend(const QString &library, const QString &version)
{
    Q_ASSERT(globalFactory->m_backendObject == 0);
    PlatformPlugin *f = globalFactory->platformPlugin();
    if (f) {
        globalFactory->m_backendObject = f->createBackend(library, version);
    }
}*/

bool FactoryPrivate::createBackend()
{
    Q_ASSERT(m_backendObject == 0);
    PlatformPlugin *f = globalFactory->platformPlugin();
    if (f) {
        m_backendObject = f->createBackend();
    }
    if (!m_backendObject) {
        // could not load a backend through the platform plugin. Falling back to the default.
#if defined(Q_WS_MAC)
        const QLatin1String pluginName("mac_qt7");
#elif defined(Q_WS_WIN)
#if defined(QT_NO_DEBUG)
        const QLatin1String pluginName("phonon_ds9");
#else
        const QLatin1String pluginName("phonon_ds9d");
#endif
#else
        const QLatin1String pluginName("xine");
#endif
        const QLatin1String suffix("/phonon_backend/");
        foreach (QString libPath, QCoreApplication::libraryPaths()) {
            libPath += suffix;
            const QDir dir(libPath);
            if (!dir.exists()) {
                pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist";
                continue;
            }
            QLibrary pluginLib(libPath + pluginName);
            if (pluginLib.load()) {
                pDebug() << Q_FUNC_INFO << "trying to load " << pluginLib.fileName();
                QPluginLoader pluginLoader(pluginLib.fileName());
                if (!pluginLoader.load()) {
                    pDebug() << Q_FUNC_INFO << "  load failed:"
                             << pluginLoader.errorString();
                    continue;
                }
                pDebug() << pluginLoader.instance();
                m_backendObject = pluginLoader.instance();
                if (m_backendObject) {
                    break;
                }
            }
        }
        if (!m_backendObject) {
            pDebug() << Q_FUNC_INFO << "phonon plugin could not be loaded:" << pluginName;
            return false;
        }
    }

    connect(m_backendObject, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
            SLOT(objectDescriptionChanged(ObjectDescriptionType)));

    return true;
}

FactoryPrivate::FactoryPrivate()
    : m_backendObject(0),
    m_platformPlugin(0),
    m_noPlatformPlugin(false)
{
    // Add the post routine to make sure that all other global statics (especially the ones from Qt)
    // are still available. If the FactoryPrivate dtor is called too late many bad things can happen
    // as the whole backend might still be alive.
    qAddPostRoutine(globalFactory.destroy);
#ifndef QT_NO_DBUS
    QDBusConnection::sessionBus().connect(QString(), QString(), "org.kde.Phonon.Factory",
            "phononBackendChanged", this, SLOT(phononBackendChanged()));
#endif
}

FactoryPrivate::~FactoryPrivate()
{
    foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
        bp->deleteBackendObject();
    }
    if (objects.size() > 0) {
        pError() << "The backend objects are not deleted as was requested.";
        qDeleteAll(objects);
    }
    delete m_backendObject;
    delete m_platformPlugin;
}

void FactoryPrivate::objectDescriptionChanged(ObjectDescriptionType type)
{
#ifdef PHONON_METHODTEST
    Q_UNUSED(type);
#else
    pDebug() << Q_FUNC_INFO << type;
    switch (type) {
    case AudioOutputDeviceType:
        emit availableAudioOutputDevicesChanged();
        break;
    default:
        break;
    }
    //emit capabilitiesChanged();
#endif // PHONON_METHODTEST
}

Factory::Sender *Factory::sender()
{
    return globalFactory;
}

bool Factory::isMimeTypeAvailable(const QString &mimeType)
{
    PlatformPlugin *f = globalFactory->platformPlugin();
    if (f) {
        return f->isMimeTypeAvailable(mimeType);
    }
    return true; // the MIME type might be supported, let BackendCapabilities find out
}

void Factory::registerFrontendObject(MediaNodePrivate *bp)
{
    globalFactory->mediaNodePrivateList.prepend(bp); // inserted last => deleted first
}

void Factory::deregisterFrontendObject(MediaNodePrivate *bp)
{
    // The Factory can already be cleaned up while there are other frontend objects still alive.
    // When those are deleted they'll call deregisterFrontendObject through ~BasePrivate
    if (!globalFactory.isDestroyed()) {
        globalFactory->mediaNodePrivateList.removeAll(bp);
    }
}

void FactoryPrivate::phononBackendChanged()
{
    if (m_backendObject) {
        foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
            bp->deleteBackendObject();
        }
        if (objects.size() > 0) {
            pDebug() << "WARNING: we were asked to change the backend but the application did\n"
                "not free all references to objects created by the factory. Therefore we can not\n"
                "change the backend without crashing. Now we have to wait for a restart to make\n"
                "backendswitching possible.";
            // in case there were objects deleted give 'em a chance to recreate
            // them now
            foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
                bp->createBackendObject();
            }
            return;
        }
        delete m_backendObject;
        m_backendObject = 0;
    }
    createBackend();
    foreach (MediaNodePrivate *bp, mediaNodePrivateList) {
        bp->createBackendObject();
    }
    emit backendChanged();
}

//X void Factory::freeSoundcardDevices()
//X {
//X     if (globalFactory->backend) {
//X         globalFactory->backend->freeSoundcardDevices();
//X     }
//X }

void FactoryPrivate::objectDestroyed(QObject * obj)
{
    //pDebug() << Q_FUNC_INFO << obj;
    objects.removeAll(obj);
}

#define FACTORY_IMPL(classname) \
QObject *Factory::create ## classname(QObject *parent) \
{ \
    if (backend()) { \
        return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent)); \
    } \
    return 0; \
}
#define FACTORY_IMPL_1ARG(classname) \
QObject *Factory::create ## classname(int arg1, QObject *parent) \
{ \
    if (backend()) { \
        return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent, QList<QVariant>() << arg1)); \
    } \
    return 0; \
}

FACTORY_IMPL(MediaObject)
FACTORY_IMPL_1ARG(Effect)
FACTORY_IMPL(VolumeFaderEffect)
FACTORY_IMPL(AudioOutput)
FACTORY_IMPL(AudioDataOutput)
FACTORY_IMPL(Visualization)
FACTORY_IMPL(VideoDataOutput)
FACTORY_IMPL(VideoWidget)

#undef FACTORY_IMPL

PlatformPlugin *FactoryPrivate::platformPlugin()
{
    if (!m_platformPlugin) {
        if (m_noPlatformPlugin) {
            return 0;
        }
#ifndef QT_NO_DBUS
        if (!QCoreApplication::instance() || QCoreApplication::applicationName().isEmpty()) {
            pWarning() << "Phonon needs QCoreApplication::applicationName to be set to export audio output names through the DBUS interface";
        }
#endif
        const QString suffix(QLatin1String("/phonon_platform"));
        Q_ASSERT(QCoreApplication::instance());
        foreach (QString libPath, QCoreApplication::libraryPaths()) {
            libPath += suffix;
            const QDir dir(libPath);
            if (!dir.exists()) {
                pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist";
                continue;
            }
            QLibrary pluginLib(libPath + QLatin1String("/kde"));
            if (pluginLib.load()) {
                pDebug() << Q_FUNC_INFO << "trying to load " << pluginLib.fileName();
                QPluginLoader pluginLoader(pluginLib.fileName());
                Q_ASSERT_X(pluginLoader.load(), Q_FUNC_INFO,
                           qPrintable(pluginLoader.errorString()));
                pDebug() << pluginLoader.instance();
                m_platformPlugin = qobject_cast<PlatformPlugin *>(pluginLoader.instance());
                pDebug() << m_platformPlugin;
                if (m_platformPlugin) {
                    return m_platformPlugin;
                }
            } else {
                pDebug() << Q_FUNC_INFO << dir.absolutePath() << "exists but the KDE platform plugin was not loadable:" << pluginLib.errorString();
            }
        }
        if (!m_platformPlugin) {
            pDebug() << Q_FUNC_INFO << "phonon_platform/kde plugin could not be loaded";
            m_noPlatformPlugin = true;
        }
    }
    return m_platformPlugin;
}

PlatformPlugin *Factory::platformPlugin()
{
    return globalFactory->platformPlugin();
}

QObject *Factory::backend(bool createWhenNull)
{
    if (globalFactory.isDestroyed()) {
        return 0;
    }
    if (createWhenNull && globalFactory->m_backendObject == 0) {
        globalFactory->createBackend();
        // XXX: might create "reentrancy" problems:
        // a method calls this method and is called again because the
        // backendChanged signal is emitted
        emit globalFactory->backendChanged();
    }
    return globalFactory->m_backendObject;
}

#define GET_STRING_PROPERTY(name) \
QString Factory::name() \
{ \
    if (globalFactory->m_backendObject) { \
        return globalFactory->m_backendObject->property(#name).toString(); \
    } \
    return QString(); \
} \

GET_STRING_PROPERTY(identifier)
GET_STRING_PROPERTY(backendName)
GET_STRING_PROPERTY(backendComment)
GET_STRING_PROPERTY(backendVersion)
GET_STRING_PROPERTY(backendIcon)
GET_STRING_PROPERTY(backendWebsite)

QObject *Factory::registerQObject(QObject *o)
{
    if (o) {
        QObject::connect(o, SIGNAL(destroyed(QObject *)), globalFactory, SLOT(objectDestroyed(QObject *)), Qt::DirectConnection);
        globalFactory->objects.append(o);
    }
    return o;
}

} //namespace Phonon

#include "moc_factory.cpp"
#include "moc_factory_p.cpp"

// vim: sw=4 ts=4
<|endoftext|>


<commit_before>
#ifndef DUNE_DETAILEL_DISCRETIZATIONS_MAPPER_MULTISCALE_HH
#define DUNE_DETAILEL_DISCRETIZATIONS_MAPPER_MULTISCALE_HH

// system
#include <map>
#include <sstream>
#include <vector>

// dune-common
#include <dune/common/exceptions.hh>

namespace Dune {

namespace Detailed {

namespace Discretizations {

namespace Mapper {

template< class IndexImp = size_t >
class Multiscale
{
public:
  typedef IndexImp IndexType;

  typedef Multiscale< IndexType > ThisType;

  static const std::string id;

  Multiscale()
    : subdomainMap_(0),
      numSubdomains_(0),
      size_(0),
      prepared_(false),
      finalized_(false)
  {}

  void prepare()
  {
    assert(!finalized_);
    if(!prepared_) {
      subdomainMap_ = new std::map< unsigned int, IndexType >();
      prepared_ = true;
    }
    return;
  } // void prepare()

  void add(const unsigned int subdomain, const IndexType size)
  {
    assert(prepared_);
    assert(!finalized_);
    assert(0 <= subdomain);
    assert(0 <= size);
    // create entry for this subdomain if needed (doing this explicitly instead of just using insert only to increment size)
    if (subdomainMap_->find(subdomain) == subdomainMap_->end()) {
      subdomainMap_->insert(std::pair< unsigned int, IndexType >(subdomain, size));
      ++numSubdomains_;
    } else {
      if (subdomainMap_->find(subdomain)->second != size)
        DUNE_THROW(Dune::InvalidStateException, "ERROR: can not add subdomain twice!");
    }
    return;
  } // void add(const unsigned int subdomain, const IndexType size)

  void finalize()
  {
    assert(prepared_);
    if(!finalized_) {
      // test for consecutive numbering of subdomains and create vector of local sizes
      for (unsigned int subdomain = 0; subdomain < numSubdomains_; ++subdomain) {
        const typename std::map< unsigned int, IndexType >::const_iterator result = subdomainMap_->find(subdomain);
        if (result == subdomainMap_->end()) {
          std::stringstream msg;
          msg << "Error in " << id << ": numbering of subdomains has to be consecutive upon calling finalize!";
          DUNE_THROW(Dune::InvalidStateException, msg.str());
        } else {
          const IndexType& localSize = result->second;
          localSizes_.push_back(localSize);
          globalStartIndices_.push_back(size_);
          size_ += localSize;
        }
      } // // test for consecutive numbering of subdomains and create vector of local sizes
      // clean up
      delete subdomainMap_;
      finalized_ = true;
    }
    return;
  } // void finalize()

  IndexType numSubdomains() const
  {
    assert(finalized_);
    return numSubdomains_;
  }

  IndexType size() const
  {
    assert(finalized_);
    return size_;
  }

  IndexType toGlobal(const unsigned int subdomain, const IndexType localIndex) const
  {
    assert(finalized_);
    assert(subdomain < numSubdomains());
    assert(0 <= localIndex);
    assert(localIndex < localSizes_[subdomain]);
    return globalStartIndices_[subdomain] + localIndex;
  } // IndexType toGlobal(const unsigned int subdomain, const InedxType localIndex) const

private:
  std::map< unsigned int, IndexType >* subdomainMap_;
  unsigned int numSubdomains_;
  unsigned int size_;
  std::vector< IndexType > localSizes_;
  std::vector< IndexType > globalStartIndices_;
  bool prepared_;
  bool finalized_;
}; // class Multiscale

template< class IndexType >
const std::string Multiscale< IndexType >::id = "detailed.discretizations.mapper.multiscale";

} // namespace Mapper

} // namespace Discretizations

} // namespace Detailed

} // namespace Dune

#endif // DUNE_DETAILEL_DISCRETIZATIONS_MAPPER_MULTISCALE_HH
<commit_msg>[mapper.multiscale] added missing include<commit_after>#ifndef DUNE_DETAILEL_DISCRETIZATIONS_MAPPER_MULTISCALE_HH
#define DUNE_DETAILEL_DISCRETIZATIONS_MAPPER_MULTISCALE_HH

#include <map>
#include <sstream>
#include <vector>
#include <assert.h>

#include <dune/common/exceptions.hh>

namespace Dune {

namespace Detailed {

namespace Discretizations {

namespace Mapper {

template< class IndexImp = size_t >
class Multiscale
{
public:
  typedef IndexImp IndexType;

  typedef Multiscale< IndexType > ThisType;

  static const std::string id;

  Multiscale()
    : subdomainMap_(0),
      numSubdomains_(0),
      size_(0),
      prepared_(false),
      finalized_(false)
  {}

  void prepare()
  {
    assert(!finalized_);
    if(!prepared_) {
      subdomainMap_ = new std::map< unsigned int, IndexType >();
      prepared_ = true;
    }
    return;
  } // void prepare()

  void add(const unsigned int subdomain, const IndexType size)
  {
    assert(prepared_);
    assert(!finalized_);
    assert(0 <= subdomain);
    assert(0 <= size);
    // create entry for this subdomain if needed (doing this explicitly instead of just using insert only to increment size)
    if (subdomainMap_->find(subdomain) == subdomainMap_->end()) {
      subdomainMap_->insert(std::pair< unsigned int, IndexType >(subdomain, size));
      ++numSubdomains_;
    } else {
      if (subdomainMap_->find(subdomain)->second != size)
        DUNE_THROW(Dune::InvalidStateException, "ERROR: can not add subdomain twice!");
    }
    return;
  } // void add(const unsigned int subdomain, const IndexType size)

  void finalize()
  {
    assert(prepared_);
    if(!finalized_) {
      // test for consecutive numbering of subdomains and create vector of local sizes
      for (unsigned int subdomain = 0; subdomain < numSubdomains_; ++subdomain) {
        const typename std::map< unsigned int, IndexType >::const_iterator result = subdomainMap_->find(subdomain);
        if (result == subdomainMap_->end()) {
          std::stringstream msg;
          msg << "Error in " << id << ": numbering of subdomains has to be consecutive upon calling finalize!";
          DUNE_THROW(Dune::InvalidStateException, msg.str());
        } else {
          const IndexType& localSize = result->second;
          localSizes_.push_back(localSize);
          globalStartIndices_.push_back(size_);
          size_ += localSize;
        }
      } // // test for consecutive numbering of subdomains and create vector of local sizes
      // clean up
      delete subdomainMap_;
      finalized_ = true;
    }
    return;
  } // void finalize()

  IndexType numSubdomains() const
  {
    assert(finalized_);
    return numSubdomains_;
  }

  IndexType size() const
  {
    assert(finalized_);
    return size_;
  }

  IndexType toGlobal(const unsigned int subdomain, const IndexType localIndex) const
  {
    assert(finalized_);
    assert(subdomain < numSubdomains());
    assert(0 <= localIndex);
    assert(localIndex < localSizes_[subdomain]);
    return globalStartIndices_[subdomain] + localIndex;
  } // IndexType toGlobal(const unsigned int subdomain, const InedxType localIndex) const

private:
  std::map< unsigned int, IndexType >* subdomainMap_;
  unsigned int numSubdomains_;
  unsigned int size_;
  std::vector< IndexType > localSizes_;
  std::vector< IndexType > globalStartIndices_;
  bool prepared_;
  bool finalized_;
}; // class Multiscale

template< class IndexType >
const std::string Multiscale< IndexType >::id = "detailed.discretizations.mapper.multiscale";

} // namespace Mapper

} // namespace Discretizations

} // namespace Detailed

} // namespace Dune

#endif // DUNE_DETAILEL_DISCRETIZATIONS_MAPPER_MULTISCALE_HH
<|endoftext|>


<commit_before><commit_msg>Ensures we don't leak handles in ProcessUtil::GetAppOutput.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2015 The Brick Authors.

#include "brick/helper.h"

#include <sstream>

#include "include/cef_parser.h"
#include "include/base/cef_logging.h"

namespace helper {

  // Transfer a V8 value to a List index.
  void
  SetListValue(
     CefRefPtr<CefListValue> list,
     int index,
     CefRefPtr<CefV8Value> value) {

    if (value->IsArray()) {
      CefRefPtr<CefListValue> new_list = CefListValue::Create();
      SetList(value, new_list);
      list->SetList(index, new_list);
    } else if (value->IsString()) {
      list->SetString(index, value->GetStringValue());
    } else if (value->IsBool()) {
      list->SetBool(index, value->GetBoolValue());
    } else if (value->IsInt()) {
      list->SetInt(index, value->GetIntValue());
    } else if (value->IsDouble()) {
      list->SetDouble(index, value->GetDoubleValue());
    } else if (value->IsNull()) {
      list->SetNull(index);
    } else {
      LOG(WARNING) << "Unknown CEF list value type";
    }
  }

  // Transfer a V8 array to a List.
  void
  SetList(CefRefPtr<CefV8Value> source, CefRefPtr<CefListValue> target) {
    ASSERT(source->IsArray());

    int arg_length = source->GetArrayLength();
    if (arg_length == 0)
      return;

    // Start with null types in all spaces.
    target->SetSize(arg_length);

    for (int i = 0; i < arg_length; ++i)
      SetListValue(target, i, source->GetValue(i));
  }

  CefRefPtr<CefV8Value>
  ListValueToV8Value(CefRefPtr<CefListValue> value, int index) {
    CefRefPtr<CefV8Value> new_value;

    CefValueType type = value->GetType(index);

    switch (type) {
      case VTYPE_LIST: {
        CefRefPtr<CefListValue> list = value->GetList(index);
        new_value = CefV8Value::CreateArray(list->GetSize());
        SetList(list, new_value);
      } break;
      case VTYPE_BOOL:
        new_value = CefV8Value::CreateBool(value->GetBool(index));
        break;
      case VTYPE_DOUBLE:
        new_value = CefV8Value::CreateDouble(value->GetDouble(index));
        break;
      case VTYPE_INT:
        new_value = CefV8Value::CreateInt(value->GetInt(index));
        break;
      case VTYPE_STRING:
        new_value = CefV8Value::CreateString(value->GetString(index));
        break;
      default:
        new_value = CefV8Value::CreateNull();
        break;
    }

    return new_value;
  }

  // Transfer a List value to a V8 array index.
  void
  SetListValue(
     CefRefPtr<CefV8Value> list,
     int index,
     CefRefPtr<CefListValue> value) {

    CefRefPtr<CefV8Value> new_value;

    CefValueType type = value->GetType(index);
    switch (type) {
      case VTYPE_LIST: {
        CefRefPtr<CefListValue> new_list = value->GetList(index);
        new_value = CefV8Value::CreateArray(new_list->GetSize());
        SetList(list, new_value);
      } break;
      case VTYPE_BOOL:
        new_value = CefV8Value::CreateBool(value->GetBool(index));
        break;
      case VTYPE_DOUBLE:
        new_value = CefV8Value::CreateDouble(value->GetDouble(index));
        break;
      case VTYPE_INT:
        new_value = CefV8Value::CreateInt(value->GetInt(index));
        break;
      case VTYPE_STRING:
        new_value = CefV8Value::CreateString(value->GetString(index));
        break;
      case VTYPE_NULL:
        new_value = CefV8Value::CreateNull();
        break;
      default:
        break;
    }

    if (new_value.get()) {
      list->SetValue(index, new_value);
    } else {
      list->SetValue(index, CefV8Value::CreateNull());
    }
  }

  // Transfer a List to a V8 array.
  void
  SetList(CefRefPtr<CefListValue> source, CefRefPtr<CefV8Value> target) {
    ASSERT(target->IsArray());

    int arg_length = source->GetSize();
    if (arg_length == 0)
      return;

    for (int i = 0; i < arg_length; ++i)
      SetListValue(target, i, source);
  }

  std::string
  DumpListValue(CefRefPtr<CefListValue> list, int index) {
    std::string result;
    switch (list->GetType(index)) {
      case VTYPE_LIST:
        result += DumpList(list->GetList(index));
        break;
      case VTYPE_BOOL:
        result += (list->GetBool(index) ? "true" : "false");
        break;
      case VTYPE_DOUBLE:
        result += std::to_string(list->GetDouble(index));
        break;
      case VTYPE_INT:
        result += std::to_string(list->GetInt(index));
        break;
      case VTYPE_STRING:
        result += '"';
        result += list->GetString(index);
        result += '"';
        break;
      case VTYPE_NULL:
        result += "null";
        break;
      default:
        result += "unknown";
    }

    return result;
  }

  std::string
  DumpList(CefRefPtr<CefListValue> list) {
    int arg_length = list->GetSize();
    if (arg_length == 0)
      return "";

    std::stringstream result;
    result << "(";
    for (int i = 0; i < arg_length; ++i) {
      result << DumpListValue(list, i);
      if (i + 1 < arg_length)
        result << ", ";
    }
    result << ")";
    return result.str();
  }

  std::string
  stringReplace(std::string src, std::string const &target, std::string const &repl) {
    // handle error situations/trivial cases

    if (!target.length()) {
      // searching for a match to the empty string will result in
      //  an infinite loop
      //  it might make sense to throw an exception for this case
        return src;
    }

    if (!src.length()) {
      return src;  // nothing to match against
    }

    std::string::size_type idx = 0;

    for (;;) {
      idx = src.find(target, idx);
      if (idx == std::string::npos)
        break;

      src.replace(idx, target.length(), repl);
      idx += repl.length();
    }

    return src;
  }

  // Retrieve the file name and mime type based on the specified url.
  bool
  ParseUrl(const std::string& url, std::string* file_name, std::string* mime_type) {
    // Retrieve the path component.
    CefURLParts parts;
    CefParseURL(url, parts);
    std::string file = CefString(&parts.path);
    if (file.size() < 2)
      return false;

    // Verify that the file name is valid.
    if (file.find("..") != std::string::npos)
      return false;

    for (const auto &c : file) {
      if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-' && c != '.' && c != '/') {
        return false;
      }
    }

    // Determine the mime type based on the file extension, if any.
    std::string ext = GetFileExtension(file);
    if (!ext.empty()) {
      *mime_type = GetMimeType(ext);
    } else {
      // Default to an html extension if none is specified.
      *mime_type = "text/html";
      file += ".html";
    }

    *file_name = file;
    return true;
  }

  uint32
  HashString(const std::string& str) {
    // Currently based on FNV-1 with 32 bit prime
    const uint32 fnv_prime = 0x811C9DC5;
    uint32 hash = 0;
    for(std::size_t i = 0; i < str.length(); i++) {
      hash *= fnv_prime;
      hash ^= str[i];
    }

    return hash;
  }

  std::string
  BaseDir(const std::string& source) {
    if (source.size() <= 1) {
      // Make sure it's possible to check the last character.
      return source;
    }

    std::string result;
    if (*(source.rbegin() + 1) == '/') {
      // Remove trailing slash if it exists.
      result = source.substr(0, source.length() - 1);
    } else {
      result = source;
    }

    size_t pos = result.find_last_of('/');
    if (pos == std::string::npos)
      return source;

    return result.substr(0, pos);
  }

  std::string
  GetFileExtension(const std::string& source) {
    size_t pos = source.rfind(".");
    if (pos != std::string::npos) {
      return source.substr(pos + 1);
    }

    return "";
  }

  std::string
  GetFileName(const std::string& source) {
    size_t pos = source.rfind("/");
    if (pos != std::string::npos) {
      return source.substr(pos + 1);
    }

    return "";
  }

  std::string
  GetMimeType(const std::string& ext) {
    if (ext == "html")
      return "text/html";
    else if (ext == "png")
      return "image/png";
    else if (ext == "jpg")
      return "image/jpeg";
    else if (ext == "gif")
      return "image/gif";
    else if (ext == "js")
      return "text/javascript";
    else if (ext == "css")
      return "text/css";
    else
      return "application/octet-strem";
  }

}  // namespace helper
<commit_msg>Fixed List to a V8 array translation<commit_after>// Copyright (c) 2015 The Brick Authors.

#include "brick/helper.h"

#include <sstream>

#include "include/cef_parser.h"
#include "include/base/cef_logging.h"

namespace helper {

  // Transfer a V8 value to a List index.
  void
  SetListValue(
     CefRefPtr<CefListValue> list,
     int index,
     CefRefPtr<CefV8Value> value) {

    if (value->IsArray()) {
      CefRefPtr<CefListValue> new_list = CefListValue::Create();
      SetList(value, new_list);
      list->SetList(index, new_list);
    } else if (value->IsString()) {
      list->SetString(index, value->GetStringValue());
    } else if (value->IsBool()) {
      list->SetBool(index, value->GetBoolValue());
    } else if (value->IsInt()) {
      list->SetInt(index, value->GetIntValue());
    } else if (value->IsDouble()) {
      list->SetDouble(index, value->GetDoubleValue());
    } else if (value->IsNull()) {
      list->SetNull(index);
    } else {
      LOG(WARNING) << "Unknown CEF list value type";
    }
  }

  // Transfer a V8 array to a List.
  void
  SetList(CefRefPtr<CefV8Value> source, CefRefPtr<CefListValue> target) {
    ASSERT(source->IsArray());

    int arg_length = source->GetArrayLength();
    if (arg_length == 0)
      return;

    // Start with null types in all spaces.
    target->SetSize(arg_length);

    for (int i = 0; i < arg_length; ++i)
      SetListValue(target, i, source->GetValue(i));
  }

  CefRefPtr<CefV8Value>
  ListValueToV8Value(CefRefPtr<CefListValue> value, int index) {
    CefRefPtr<CefV8Value> new_value;

    CefValueType type = value->GetType(index);

    switch (type) {
      case VTYPE_LIST: {
        CefRefPtr<CefListValue> list = value->GetList(index);
        new_value = CefV8Value::CreateArray(list->GetSize());
        SetList(list, new_value);
      } break;
      case VTYPE_BOOL:
        new_value = CefV8Value::CreateBool(value->GetBool(index));
        break;
      case VTYPE_DOUBLE:
        new_value = CefV8Value::CreateDouble(value->GetDouble(index));
        break;
      case VTYPE_INT:
        new_value = CefV8Value::CreateInt(value->GetInt(index));
        break;
      case VTYPE_STRING:
        new_value = CefV8Value::CreateString(value->GetString(index));
        break;
      default:
        new_value = CefV8Value::CreateNull();
        break;
    }

    return new_value;
  }

  // Transfer a List value to a V8 array index.
  void
  SetListValue(
     CefRefPtr<CefV8Value> list,
     int index,
     CefRefPtr<CefListValue> value) {

    CefRefPtr<CefV8Value> new_value;

    CefValueType type = value->GetType(index);
    switch (type) {
      case VTYPE_LIST: {
        CefRefPtr<CefListValue> new_list = value->GetList(index);
        new_value = CefV8Value::CreateArray(new_list->GetSize());
        SetList(new_list, new_value);
      } break;
      case VTYPE_BOOL:
        new_value = CefV8Value::CreateBool(value->GetBool(index));
        break;
      case VTYPE_DOUBLE:
        new_value = CefV8Value::CreateDouble(value->GetDouble(index));
        break;
      case VTYPE_INT:
        new_value = CefV8Value::CreateInt(value->GetInt(index));
        break;
      case VTYPE_STRING:
        new_value = CefV8Value::CreateString(value->GetString(index));
        break;
      case VTYPE_NULL:
        new_value = CefV8Value::CreateNull();
        break;
      default:
        break;
    }

    if (new_value.get()) {
      list->SetValue(index, new_value);
    } else {
      list->SetValue(index, CefV8Value::CreateNull());
    }
  }

  // Transfer a List to a V8 array.
  void
  SetList(CefRefPtr<CefListValue> source, CefRefPtr<CefV8Value> target) {
    ASSERT(target->IsArray());

    int arg_length = source->GetSize();
    if (arg_length == 0)
      return;

    for (int i = 0; i < arg_length; ++i)
      SetListValue(target, i, source);
  }

  std::string
  DumpListValue(CefRefPtr<CefListValue> list, int index) {
    std::string result;
    switch (list->GetType(index)) {
      case VTYPE_LIST:
        result += DumpList(list->GetList(index));
        break;
      case VTYPE_BOOL:
        result += (list->GetBool(index) ? "true" : "false");
        break;
      case VTYPE_DOUBLE:
        result += std::to_string(list->GetDouble(index));
        break;
      case VTYPE_INT:
        result += std::to_string(list->GetInt(index));
        break;
      case VTYPE_STRING:
        result += '"';
        result += list->GetString(index);
        result += '"';
        break;
      case VTYPE_NULL:
        result += "null";
        break;
      default:
        result += "unknown";
    }

    return result;
  }

  std::string
  DumpList(CefRefPtr<CefListValue> list) {
    int arg_length = list->GetSize();
    if (arg_length == 0)
      return "";

    std::stringstream result;
    result << "(";
    for (int i = 0; i < arg_length; ++i) {
      result << DumpListValue(list, i);
      if (i + 1 < arg_length)
        result << ", ";
    }
    result << ")";
    return result.str();
  }

  std::string
  stringReplace(std::string src, std::string const &target, std::string const &repl) {
    // handle error situations/trivial cases

    if (!target.length()) {
      // searching for a match to the empty string will result in
      //  an infinite loop
      //  it might make sense to throw an exception for this case
        return src;
    }

    if (!src.length()) {
      return src;  // nothing to match against
    }

    std::string::size_type idx = 0;

    for (;;) {
      idx = src.find(target, idx);
      if (idx == std::string::npos)
        break;

      src.replace(idx, target.length(), repl);
      idx += repl.length();
    }

    return src;
  }

  // Retrieve the file name and mime type based on the specified url.
  bool
  ParseUrl(const std::string& url, std::string* file_name, std::string* mime_type) {
    // Retrieve the path component.
    CefURLParts parts;
    CefParseURL(url, parts);
    std::string file = CefString(&parts.path);
    if (file.size() < 2)
      return false;

    // Verify that the file name is valid.
    if (file.find("..") != std::string::npos)
      return false;

    for (const auto &c : file) {
      if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-' && c != '.' && c != '/') {
        return false;
      }
    }

    // Determine the mime type based on the file extension, if any.
    std::string ext = GetFileExtension(file);
    if (!ext.empty()) {
      *mime_type = GetMimeType(ext);
    } else {
      // Default to an html extension if none is specified.
      *mime_type = "text/html";
      file += ".html";
    }

    *file_name = file;
    return true;
  }

  uint32
  HashString(const std::string& str) {
    // Currently based on FNV-1 with 32 bit prime
    const uint32 fnv_prime = 0x811C9DC5;
    uint32 hash = 0;
    for(std::size_t i = 0; i < str.length(); i++) {
      hash *= fnv_prime;
      hash ^= str[i];
    }

    return hash;
  }

  std::string
  BaseDir(const std::string& source) {
    if (source.size() <= 1) {
      // Make sure it's possible to check the last character.
      return source;
    }

    std::string result;
    if (*(source.rbegin() + 1) == '/') {
      // Remove trailing slash if it exists.
      result = source.substr(0, source.length() - 1);
    } else {
      result = source;
    }

    size_t pos = result.find_last_of('/');
    if (pos == std::string::npos)
      return source;

    return result.substr(0, pos);
  }

  std::string
  GetFileExtension(const std::string& source) {
    size_t pos = source.rfind(".");
    if (pos != std::string::npos) {
      return source.substr(pos + 1);
    }

    return "";
  }

  std::string
  GetFileName(const std::string& source) {
    size_t pos = source.rfind("/");
    if (pos != std::string::npos) {
      return source.substr(pos + 1);
    }

    return "";
  }

  std::string
  GetMimeType(const std::string& ext) {
    if (ext == "html")
      return "text/html";
    else if (ext == "png")
      return "image/png";
    else if (ext == "jpg")
      return "image/jpeg";
    else if (ext == "gif")
      return "image/gif";
    else if (ext == "js")
      return "text/javascript";
    else if (ext == "css")
      return "text/css";
    else
      return "application/octet-strem";
  }

}  // namespace helper
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/detail/sendrecvop_utils.h"

#include <sys/time.h>
#include <thread>  // NOLINT

#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "paddle/fluid/framework/data_type.h"
#include "paddle/fluid/operators/detail/bytebuffer_stream.h"
#include "paddle/fluid/operators/detail/proto_encoder_helper.h"
#include "paddle/fluid/operators/detail/variable_response.h"
#include "paddle/fluid/platform/profiler.h"

namespace paddle {
namespace operators {
namespace detail {

using VarMsg = sendrecv::VariableMessage;

VarMsg::Type DataTypeToEnum(std::type_index type) {
  if (typeid(platform::float16).hash_code() == type.hash_code()) {
    return VarMsg::FP16;
  } else if (typeid(const float).hash_code() == type.hash_code()) {
    // CPPLint complains Using C-style cast.  Use static_cast<float>() instead
    // One fix to this is to replace float with const float because
    // typeid(T) == typeid(const T)
    // http://en.cppreference.com/w/cpp/language/typeid
    return VarMsg::FP32;
  } else if (typeid(const double).hash_code() == type.hash_code()) {
    return VarMsg::FP64;
  } else if (typeid(const int).hash_code() == type.hash_code()) {
    return VarMsg::INT32;
  } else if (typeid(const int64_t).hash_code() == type.hash_code()) {
    return VarMsg::INT64;
  } else if (typeid(const bool).hash_code() == type.hash_code()) {
    return VarMsg::BOOL;
  } else {
    PADDLE_THROW("Not supported");
  }
}

void GetTensorPayload(framework::Variable* var,
                      const platform::DeviceContext& ctx, VarMsg* request,
                      void** payload, size_t* payload_size) {
  auto tensor = var->Get<framework::LoDTensor>();
  // FIXME(wuyi): data types in send_recv.proto is not synced with
  // framework.proto
  request->set_data_type(DataTypeToEnum(tensor.type()));
  for (auto& dim : framework::vectorize(tensor.dims())) {
    request->add_dims(dim);
  }
  const framework::LoD lod = tensor.lod();
  if (lod.size() > 0) {
    request->set_lod_level(lod.size());
    for (auto& each : lod) {
      VarMsg::LodData* lod_inner = request->add_lod();
      for (auto& d : each) {
        lod_inner->add_lod_data(d);
      }
    }
  }
  if (platform::is_gpu_place(ctx.GetPlace())) {
#ifdef PADDLE_WITH_CUDA
    PADDLE_ENFORCE(platform::is_gpu_place(tensor.place()));
    platform::CPUPlace cpu;
    auto& gpu_dev_ctx = static_cast<const platform::CUDADeviceContext&>(ctx);
    auto copy_size = tensor.numel() * framework::SizeOfType(tensor.type());
    *payload = memory::Alloc(cpu, copy_size);

    memory::Copy(cpu, *payload, boost::get<platform::CUDAPlace>(tensor.place()),
                 reinterpret_cast<const void*>(tensor.data<void>()), copy_size,
                 gpu_dev_ctx.stream());
    ctx.Wait();
#endif
  } else {
    *payload = tensor.data<void>();
  }
  *payload_size = tensor.numel() * framework::SizeOfType(tensor.type());
}

void GetSelectedRowsPayload(framework::Variable* var,
                            const platform::DeviceContext& ctx, VarMsg* request,
                            void** payload, size_t* payload_size) {
  auto* slr = var->GetMutable<framework::SelectedRows>();
  request->set_data_type(DataTypeToEnum(slr->value().type()));
  request->set_lod_level(0);
  request->set_slr_height(slr->height());

  for (auto& dim : framework::vectorize(slr->value().dims())) {
    request->add_dims(dim);
  }

  auto* tensor = slr->mutable_value();
  if (platform::is_gpu_place(ctx.GetPlace())) {
#ifdef PADDLE_WITH_CUDA
    platform::CPUPlace cpu;
    auto& gpu_dev_ctx = static_cast<const platform::CUDADeviceContext&>(ctx);
    auto copy_size = tensor->numel() * framework::SizeOfType(tensor->type());
    *payload = memory::Alloc(cpu, copy_size);
    memory::Copy(cpu, *payload,
                 boost::get<platform::CUDAPlace>(tensor->place()),
                 reinterpret_cast<const void*>(tensor->data<void>()), copy_size,
                 gpu_dev_ctx.stream());
    ctx.Wait();
#endif
  } else {
    *payload = slr->mutable_value()->data<void>();
  }
  *payload_size = tensor->numel() * framework::SizeOfType(tensor->type());
}

void SerializeToByteBuffer(const std::string& name, framework::Variable* var,
                           const platform::DeviceContext& ctx,
                           ::grpc::ByteBuffer* msg,
                           const std::string& out_name) {
  // Default DestroyCallback does nothing, When using GPU
  // the CPU buffer need to be freed.
  DestroyCallback destroy_callback = [](void* backing) {};
  VarMsg request;
  void* payload = nullptr;
  size_t payload_size;

  request.set_varname(name);
  // Note: normally the profiler is enabled in 1 trainer, hence only
  // 1 trainer returns true for ShouldSendProfileState(). It tells PS
  // servers the trainer's profiling state so that PS can follow the
  // trainer.
  request.set_profile(platform::IsProfileEnabled());
  if (!out_name.empty()) {
    request.set_out_varname(out_name);
  }
  if (var->IsType<framework::LoDTensor>()) {
    request.set_type(::sendrecv::LOD_TENSOR);
    GetTensorPayload(var, ctx, &request, &payload, &payload_size);
  } else if (var->IsType<framework::SelectedRows>()) {
    request.set_type(::sendrecv::SELECTED_ROWS);
    GetSelectedRowsPayload(var, ctx, &request, &payload, &payload_size);
  } else {
    PADDLE_THROW("Serialize does not support type: %s",
                 typeid(var->Type()).name());
  }

  if (platform::is_gpu_place(ctx.GetPlace())) {
    // GPU data is copied to CPU buffer when sending,
    // free the buffer when possible.
    destroy_callback = [](void* backing) {
      platform::CPUPlace cpu;
      memory::Free(cpu, backing);
    };
  }

  std::string header;
  request.AppendToString(&header);
  auto buffer = std::unique_ptr<char[]>(new char[1024]);
  void* buf = buffer.get();
  ProtoEncodeHelper e(static_cast<char*>(buf), 1024);
  e.WriteRawBytes(std::string(header.data(), header.size()));
  e.WriteVarlengthBeginning(VarMsg::kSerializedFieldNumber, payload_size);

  // steal reference of tensor data
  ::grpc::Slice slices[4];  // metadata, tensor, rows meta, rows
  int num_slices = 2;       // only SelectedRows have rows buffer
  slices[0] = ::grpc::Slice(e.size());
  memcpy(const_cast<uint8_t*>(slices[0].begin()), e.data(), e.size());
  slices[1] = ::grpc::Slice(
      grpc_slice_new_with_user_data(payload, payload_size, destroy_callback,
                                    static_cast<char*>(payload)),
      ::grpc::Slice::STEAL_REF);

  if (var->IsType<framework::SelectedRows>()) {
    auto* slr = var->GetMutable<framework::SelectedRows>();
    ProtoEncodeHelper e2(static_cast<char*>(buf), 128);
    size_t rows_memory_size =
        slr->rows().size() * framework::SizeOfType(typeid(int64_t));
    e2.WriteVarlengthBeginning(VarMsg::kRowsFieldNumber, rows_memory_size);
    slices[2] = ::grpc::Slice(e2.size());
    memcpy(const_cast<uint8_t*>(slices[2].begin()), e2.data(), e2.size());

    slices[3] = ::grpc::Slice(
        grpc_slice_new_with_user_data(
            const_cast<void*>(
                reinterpret_cast<const void*>(slr->rows().data())),
            rows_memory_size, [](void* backing) {},
            const_cast<char*>(
                reinterpret_cast<const char*>(slr->rows().data()))),
        ::grpc::Slice::STEAL_REF);
    num_slices = 4;
  }

  ::grpc::ByteBuffer tmp(&slices[0], num_slices);
  msg->Swap(&tmp);
}

void DeserializeFromByteBuffer(const ::grpc::ByteBuffer& msg,
                               const platform::DeviceContext& ctx,
                               const framework::Scope* scope,
                               framework::Variable** var) {
  operators::detail::VariableResponse resp(scope, &ctx);
  PADDLE_ENFORCE(resp.Parse(msg) == 0, "parse bytebuffer to tensor error!");
  *var = resp.GetVar();
}

}  // namespace detail
}  // namespace operators
}  // namespace paddle
<commit_msg>cast data type<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/detail/sendrecvop_utils.h"

#include <sys/time.h>
#include <thread>  // NOLINT

#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "paddle/fluid/framework/data_type.h"
#include "paddle/fluid/operators/detail/bytebuffer_stream.h"
#include "paddle/fluid/operators/detail/proto_encoder_helper.h"
#include "paddle/fluid/operators/detail/variable_response.h"
#include "paddle/fluid/platform/profiler.h"

namespace paddle {
namespace operators {
namespace detail {

using VarMsg = sendrecv::VariableMessage;

void GetTensorPayload(framework::Variable* var,
                      const platform::DeviceContext& ctx, VarMsg* request,
                      void** payload, size_t* payload_size) {
  auto tensor = var->Get<framework::LoDTensor>();
  // FIXME(wuyi): data types in send_recv.proto is copied from
  // framework.proto
  request->set_data_type(
      static_cast<VarMsg::Type>(framework::ToDataType(tensor.type())));
  for (auto& dim : framework::vectorize(tensor.dims())) {
    request->add_dims(dim);
  }
  const framework::LoD lod = tensor.lod();
  if (lod.size() > 0) {
    request->set_lod_level(lod.size());
    for (auto& each : lod) {
      VarMsg::LodData* lod_inner = request->add_lod();
      for (auto& d : each) {
        lod_inner->add_lod_data(d);
      }
    }
  }
  if (platform::is_gpu_place(ctx.GetPlace())) {
#ifdef PADDLE_WITH_CUDA
    PADDLE_ENFORCE(platform::is_gpu_place(tensor.place()));
    platform::CPUPlace cpu;
    auto& gpu_dev_ctx = static_cast<const platform::CUDADeviceContext&>(ctx);
    auto copy_size = tensor.numel() * framework::SizeOfType(tensor.type());
    *payload = memory::Alloc(cpu, copy_size);

    memory::Copy(cpu, *payload, boost::get<platform::CUDAPlace>(tensor.place()),
                 reinterpret_cast<const void*>(tensor.data<void>()), copy_size,
                 gpu_dev_ctx.stream());
    ctx.Wait();
#endif
  } else {
    *payload = tensor.data<void>();
  }
  *payload_size = tensor.numel() * framework::SizeOfType(tensor.type());
}

void GetSelectedRowsPayload(framework::Variable* var,
                            const platform::DeviceContext& ctx, VarMsg* request,
                            void** payload, size_t* payload_size) {
  auto* slr = var->GetMutable<framework::SelectedRows>();
  request->set_data_type(
      static_cast<VarMsg::Type>(framework::ToDataType(slr->value().type())));
  request->set_lod_level(0);
  request->set_slr_height(slr->height());

  for (auto& dim : framework::vectorize(slr->value().dims())) {
    request->add_dims(dim);
  }

  auto* tensor = slr->mutable_value();
  if (platform::is_gpu_place(ctx.GetPlace())) {
#ifdef PADDLE_WITH_CUDA
    platform::CPUPlace cpu;
    auto& gpu_dev_ctx = static_cast<const platform::CUDADeviceContext&>(ctx);
    auto copy_size = tensor->numel() * framework::SizeOfType(tensor->type());
    *payload = memory::Alloc(cpu, copy_size);
    memory::Copy(cpu, *payload,
                 boost::get<platform::CUDAPlace>(tensor->place()),
                 reinterpret_cast<const void*>(tensor->data<void>()), copy_size,
                 gpu_dev_ctx.stream());
    ctx.Wait();
#endif
  } else {
    *payload = slr->mutable_value()->data<void>();
  }
  *payload_size = tensor->numel() * framework::SizeOfType(tensor->type());
}

void SerializeToByteBuffer(const std::string& name, framework::Variable* var,
                           const platform::DeviceContext& ctx,
                           ::grpc::ByteBuffer* msg,
                           const std::string& out_name) {
  // Default DestroyCallback does nothing, When using GPU
  // the CPU buffer need to be freed.
  DestroyCallback destroy_callback = [](void* backing) {};
  VarMsg request;
  void* payload = nullptr;
  size_t payload_size;

  request.set_varname(name);
  // Note: normally the profiler is enabled in 1 trainer, hence only
  // 1 trainer returns true for ShouldSendProfileState(). It tells PS
  // servers the trainer's profiling state so that PS can follow the
  // trainer.
  request.set_profile(platform::IsProfileEnabled());
  if (!out_name.empty()) {
    request.set_out_varname(out_name);
  }
  if (var->IsType<framework::LoDTensor>()) {
    request.set_type(::sendrecv::LOD_TENSOR);
    GetTensorPayload(var, ctx, &request, &payload, &payload_size);
  } else if (var->IsType<framework::SelectedRows>()) {
    request.set_type(::sendrecv::SELECTED_ROWS);
    GetSelectedRowsPayload(var, ctx, &request, &payload, &payload_size);
  } else {
    PADDLE_THROW("Serialize does not support type: %s",
                 typeid(var->Type()).name());
  }

  if (platform::is_gpu_place(ctx.GetPlace())) {
    // GPU data is copied to CPU buffer when sending,
    // free the buffer when possible.
    destroy_callback = [](void* backing) {
      platform::CPUPlace cpu;
      memory::Free(cpu, backing);
    };
  }

  std::string header;
  request.AppendToString(&header);
  auto buffer = std::unique_ptr<char[]>(new char[1024]);
  void* buf = buffer.get();
  ProtoEncodeHelper e(static_cast<char*>(buf), 1024);
  e.WriteRawBytes(std::string(header.data(), header.size()));
  e.WriteVarlengthBeginning(VarMsg::kSerializedFieldNumber, payload_size);
  // steal reference of tensor data
  ::grpc::Slice slices[4];  // metadata, tensor, rows meta, rows
  int num_slices = 2;       // only SelectedRows have rows buffer
  slices[0] = ::grpc::Slice(e.size());
  memcpy(const_cast<uint8_t*>(slices[0].begin()), e.data(), e.size());
  slices[1] = ::grpc::Slice(
      grpc_slice_new_with_user_data(payload, payload_size, destroy_callback,
                                    static_cast<char*>(payload)),
      ::grpc::Slice::STEAL_REF);

  if (var->IsType<framework::SelectedRows>()) {
    auto* slr = var->GetMutable<framework::SelectedRows>();
    ProtoEncodeHelper e2(static_cast<char*>(buf), 128);
    size_t rows_memory_size =
        slr->rows().size() * framework::SizeOfType(typeid(int64_t));
    e2.WriteVarlengthBeginning(VarMsg::kRowsFieldNumber, rows_memory_size);
    slices[2] = ::grpc::Slice(e2.size());
    memcpy(const_cast<uint8_t*>(slices[2].begin()), e2.data(), e2.size());

    slices[3] = ::grpc::Slice(
        grpc_slice_new_with_user_data(
            const_cast<void*>(
                reinterpret_cast<const void*>(slr->rows().data())),
            rows_memory_size, [](void* backing) {},
            const_cast<char*>(
                reinterpret_cast<const char*>(slr->rows().data()))),
        ::grpc::Slice::STEAL_REF);
    num_slices = 4;
  }

  ::grpc::ByteBuffer tmp(&slices[0], num_slices);
  msg->Swap(&tmp);
}

void DeserializeFromByteBuffer(const ::grpc::ByteBuffer& msg,
                               const platform::DeviceContext& ctx,
                               const framework::Scope* scope,
                               framework::Variable** var) {
  operators::detail::VariableResponse resp(scope, &ctx);
  PADDLE_ENFORCE(resp.Parse(msg) == 0, "parse bytebuffer to tensor error!");
  *var = resp.GetVar();
}

}  // namespace detail
}  // namespace operators
}  // namespace paddle
<|endoftext|>


<commit_before>#include "catch/catch.hpp"

#include "mikmod_sound.h"
#include "main.h"
#include "exception.h"
#include "stdio.h"

std::vector<uint8_t> loadFromFile(const std::string& filePath)
{
    auto f = fopen(filePath.c_str(), "rb");
    if (!f) return std::vector<uint8_t>();
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    fseek(f, 0, SEEK_SET);  //same as rewind(f);
    std::vector<uint8_t> data(fsize);
    fread(data.data(), fsize, 1, f);
    fclose(f);
    return data;
}

TEST_CASE("MikmodSoundTest")
{
    MikmodSound sound;

    SECTION("Exception on non existing file")
    {
        REQUIRE_THROWS_AS(sound.playModule("non_existing_file.xm");, Exception);
        REQUIRE_THROWS_AS(sound.loadSample("non_existing_file.wav");, Exception);
    }

    SECTION("Check rendered music output")
    {
        sound.playModule(TestParams::testDataDir + "test_music.xm");
        size_t frames = 1000;
        std::vector<uint8_t> data(frames * 4);
        sound.renderAudioFrames(frames, data.data());

        // auto fp = fopen("test_music_render.raw", "wb");
        // REQUIRE(fp != nullptr);

        // fwrite(data.data(), 1, data.size(), fp);
        // fclose(fp);

        // auto refData = loadFromFile(TestParams::testDataDir + "test_music_render.raw");
        // REQUIRE(refData == data);
		// @todo check against reference
    }

    SECTION("Play invalid sample")
    {
        REQUIRE_THROWS_AS(sound.playSample(0);, Exception);
        REQUIRE_THROWS_AS(sound.playSample(10);, Exception);
        REQUIRE_THROWS_AS(sound.playSample(100000);, Exception);
    }

    SECTION("Play Samples")
    {
        auto id = sound.loadSample(TestParams::testDataDir + "sample.wav");
        sound.playSample(id);
        size_t frames = 1000;
        std::vector<uint8_t> data(frames * 4);
        sound.renderAudioFrames(frames, data.data());

        //@todo check against reference
    }
}
<commit_msg>Properly ignore return value<commit_after>#include "catch/catch.hpp"

#include "mikmod_sound.h"
#include "main.h"
#include "exception.h"
#include "stdio.h"

std::vector<uint8_t> loadFromFile(const std::string& filePath)
{
    auto f = fopen(filePath.c_str(), "rb");
    if (!f) return std::vector<uint8_t>();
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    fseek(f, 0, SEEK_SET);  //same as rewind(f);
    std::vector<uint8_t> data(fsize);
    (void)fread(data.data(), fsize, 1, f);
    fclose(f);
    return data;
}

TEST_CASE("MikmodSoundTest")
{
    MikmodSound sound;

    SECTION("Exception on non existing file")
    {
        REQUIRE_THROWS_AS(sound.playModule("non_existing_file.xm");, Exception);
        REQUIRE_THROWS_AS(sound.loadSample("non_existing_file.wav");, Exception);
    }

    SECTION("Check rendered music output")
    {
        sound.playModule(TestParams::testDataDir + "test_music.xm");
        size_t frames = 1000;
        std::vector<uint8_t> data(frames * 4);
        sound.renderAudioFrames(frames, data.data());

        // auto fp = fopen("test_music_render.raw", "wb");
        // REQUIRE(fp != nullptr);

        // fwrite(data.data(), 1, data.size(), fp);
        // fclose(fp);

        // auto refData = loadFromFile(TestParams::testDataDir + "test_music_render.raw");
        // REQUIRE(refData == data);
		// @todo check against reference
    }

    SECTION("Play invalid sample")
    {
        REQUIRE_THROWS_AS(sound.playSample(0);, Exception);
        REQUIRE_THROWS_AS(sound.playSample(10);, Exception);
        REQUIRE_THROWS_AS(sound.playSample(100000);, Exception);
    }

    SECTION("Play Samples")
    {
        auto id = sound.loadSample(TestParams::testDataDir + "sample.wav");
        sound.playSample(id);
        size_t frames = 1000;
        std::vector<uint8_t> data(frames * 4);
        sound.renderAudioFrames(frames, data.data());

        //@todo check against reference
    }
}
<|endoftext|>


<commit_before>#include "nodetests.h"
#include "yaml-cpp/yaml.h"

namespace {
	struct TEST {
		TEST(): ok(false) {}
		TEST(bool ok_): ok(ok_) {}
		TEST(const char *error_): ok(false), error(error_) {}

		bool ok;
		std::string error;
	};
}

#define YAML_ASSERT(cond) do { if(!(cond)) return "  Assert failed: " #cond; } while(false)

namespace Test
{
	namespace Node
	{
		TEST SimpleScalar()
		{
			YAML::Node node = YAML::Node("Hello, World!");
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<std::string>() == "Hello, World!");
			return true;
		}

		TEST IntScalar()
		{
			YAML::Node node = YAML::Node(15);
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<int>() == 15);
			return true;
		}

		TEST SimpleSequence()
		{
			YAML::Node node;
			node.append(10);
			node.append("foo");
			node.append("monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 3);
			YAML_ASSERT(node[0].as<int>() == 10);
			YAML_ASSERT(node[1].as<std::string>() == "foo");
			YAML_ASSERT(node[1].as<std::string>() == "monkey");
			return true;
		}
	}

	void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
		TEST ret;
		try {
			ret = test();
		} catch(...) {
			ret.ok = false;
		}
		if(ret.ok) {
			passed++;
		} else {
			std::cout << "Node test failed: " << name << "\n";
			if(ret.error != "")
				std::cout << ret.error << "\n";
		}
		total++;
	}

	bool RunNodeTests()
	{
		int passed = 0;
		int total = 0;

		RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total);
		RunNodeTest(&Node::IntScalar, "int scalar", passed, total);
		RunNodeTest(&Node::SimpleSequence, "simple sequence", passed, total);

		std::cout << "Node tests: " << passed << "/" << total << " passed\n";
		return passed == total;
	}
}
<commit_msg>Added some small map tests<commit_after>#include "nodetests.h"
#include "yaml-cpp/yaml.h"

namespace {
	struct TEST {
		TEST(): ok(false) {}
		TEST(bool ok_): ok(ok_) {}
		TEST(const char *error_): ok(false), error(error_) {}

		bool ok;
		std::string error;
	};
}

#define YAML_ASSERT(cond) do { if(!(cond)) return "  Assert failed: " #cond; } while(false)

namespace Test
{
	namespace Node
	{
		TEST SimpleScalar()
		{
			YAML::Node node = YAML::Node("Hello, World!");
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<std::string>() == "Hello, World!");
			return true;
		}

		TEST IntScalar()
		{
			YAML::Node node = YAML::Node(15);
			YAML_ASSERT(node.Type() == YAML::NodeType::Scalar);
			YAML_ASSERT(node.as<int>() == 15);
			return true;
		}

		TEST SimpleSequence()
		{
			YAML::Node node;
			node.append(10);
			node.append("foo");
			node.append("monkey");
			YAML_ASSERT(node.Type() == YAML::NodeType::Sequence);
			YAML_ASSERT(node.size() == 3);
			YAML_ASSERT(node[0].as<int>() == 10);
			YAML_ASSERT(node[1].as<std::string>() == "foo");
			YAML_ASSERT(node[1].as<std::string>() == "monkey");
			return true;
		}

		TEST SimpleMap()
		{
			YAML::Node node;
			node["key"] = "value";
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node["key"].as<std::string>() == "value");
			YAML_ASSERT(node.size() == 1);
			return true;
		}

		TEST MapWithUndefinedValues()
		{
			YAML::Node node;
			node["key"] = "value";
			node["undefined"];
			YAML_ASSERT(node.Type() == YAML::NodeType::Map);
			YAML_ASSERT(node["key"].as<std::string>() == "value");
			YAML_ASSERT(node.size() == 1);
			return true;
		}
	}

	void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
		TEST ret;
		try {
			ret = test();
		} catch(...) {
			ret.ok = false;
		}
		if(ret.ok) {
			passed++;
		} else {
			std::cout << "Node test failed: " << name << "\n";
			if(ret.error != "")
				std::cout << ret.error << "\n";
		}
		total++;
	}

	bool RunNodeTests()
	{
		int passed = 0;
		int total = 0;

		RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total);
		RunNodeTest(&Node::IntScalar, "int scalar", passed, total);
		RunNodeTest(&Node::SimpleSequence, "simple sequence", passed, total);
		RunNodeTest(&Node::SimpleMap, "simple map", passed, total);
		RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total);

		std::cout << "Node tests: " << passed << "/" << total << " passed\n";
		return passed == total;
	}
}
<|endoftext|>


<commit_before>// This file is part of Poseidon.
// Copyleft 2020, LH_Mouse. All wrongs reserved.

#ifndef POSEIDON_NETWORK_ABSTRACT_STREAM_SOCKET_HPP_
#define POSEIDON_NETWORK_ABSTRACT_STREAM_SOCKET_HPP_

#include "abstract_socket.hpp"
#include <rocket/linear_buffer.hpp>

namespace poseidon {

class Abstract_Stream_Socket
  : public Abstract_Socket
  {
  public:
    using base_type = Abstract_Socket;

  private:
    mutable Si_Mutex m_mutex;
    Connection_State m_cstate = connection_state_initial;
    ::rocket::linear_buffer m_wqueue;  // write queue

  public:
    explicit
    Abstract_Stream_Socket(unique_posix_fd&& fd)
      : base_type(::std::move(fd))
      { }

    ASTERIA_NONCOPYABLE_DESTRUCTOR(Abstract_Stream_Socket);

  private:
    inline
    IO_Result
    do_call_stream_preshutdown_nolock()
    noexcept;

    inline
    void
    do_async_shutdown_nolock()
    noexcept;

    // Reads some data.
    // `lock` will lock `*this` after the call.
    // `hint` is used as the I/O buffer. `size` specifies the maximum number of
    // bytes to read.
    IO_Result
    do_on_async_poll_read(Si_Mutex::unique_lock& lock, void* hint, size_t size)
    final;

    // Returns the size of data pending for writing.
    // `lock` will lock `*this` after the call.
    size_t
    do_write_queue_size(Si_Mutex::unique_lock& lock)
    const final;

    // Writes some data.
    // `lock` will lock `*this` after the call.
    // `hint` and `size` are ignored.
    IO_Result
    do_on_async_poll_write(Si_Mutex::unique_lock& lock, void* hint, size_t size)
    final;

    // Notifies a full-duplex channel has been closed.
    void
    do_on_async_poll_shutdown(int err)
    final;

  protected:
    // Performs outgoing connecting preparation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    // This function is not called on incoming connections.
    virtual
    void
    do_stream_preconnect_nolock()
      = 0;

    // Performs read operation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    virtual
    IO_Result
    do_stream_read_nolock(void* data, size_t size)
      = 0;

    // Performs write operation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    virtual
    IO_Result
    do_stream_write_nolock(const void* data, size_t size)
      = 0;

    // Performs shutdown preparation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    // This function shall return `io_result_eof` if the shutdown operation has
    // either completed or failed due to some irrecoverable errors.
    virtual
    IO_Result
    do_stream_preshutdown_nolock()
      = 0;

    // Notifies a full-duplex channel has been established.
    // Please mind thread safety, as this function is called by the network thread.
    virtual
    void
    do_on_async_establish()
      = 0;

    // Consumes an incoming packet.
    // Please mind thread safety, as this function is called by the network thread.
    virtual
    void
    do_on_async_receive(void* data, size_t size)
      = 0;

    // Notifies a socket has been closed.
    // Please mind thread safety, as this function is called by the network thread.
    virtual
    void
    do_on_async_shutdown(int err)
      = 0;

    // Initiates a new connection to the specified address.
    void
    do_async_connect(const Socket_Address& addr);

  public:
    // Enqueues some data for writing.
    // This function returns `true` if the data have been queued, or `false` if a
    // shutdown request has been initiated.
    // This function is thread-safe.
    bool
    async_send(const void* data, size_t size);

    // Initiates normal closure of this stream.
    // This function returns `true` if the shutdown request completes immediately,
    // or `false` if there are still data pending. In either case, the socket is
    // considered closed. No further date may be read from or written through it.
    // Note half-closed connections are not supported.
    bool
    async_shutdown()
    noexcept;
  };

}  // namespace poseidon

#endif
<commit_msg>network/abstract_stream_socket: Update comments<commit_after>// This file is part of Poseidon.
// Copyleft 2020, LH_Mouse. All wrongs reserved.

#ifndef POSEIDON_NETWORK_ABSTRACT_STREAM_SOCKET_HPP_
#define POSEIDON_NETWORK_ABSTRACT_STREAM_SOCKET_HPP_

#include "abstract_socket.hpp"
#include <rocket/linear_buffer.hpp>

namespace poseidon {

class Abstract_Stream_Socket
  : public Abstract_Socket
  {
  public:
    using base_type = Abstract_Socket;

  private:
    mutable Si_Mutex m_mutex;
    Connection_State m_cstate = connection_state_initial;
    ::rocket::linear_buffer m_wqueue;  // write queue

  public:
    explicit
    Abstract_Stream_Socket(unique_posix_fd&& fd)
      : base_type(::std::move(fd))
      { }

    ASTERIA_NONCOPYABLE_DESTRUCTOR(Abstract_Stream_Socket);

  private:
    inline
    IO_Result
    do_call_stream_preshutdown_nolock()
    noexcept;

    inline
    void
    do_async_shutdown_nolock()
    noexcept;

    // Reads some data.
    // `lock` will lock `*this` after the call.
    // `hint` is used as the I/O buffer. `size` specifies the maximum number of
    // bytes to read.
    IO_Result
    do_on_async_poll_read(Si_Mutex::unique_lock& lock, void* hint, size_t size)
    final;

    // Returns the size of data pending for writing.
    // `lock` will lock `*this` after the call.
    size_t
    do_write_queue_size(Si_Mutex::unique_lock& lock)
    const final;

    // Writes some data.
    // `lock` will lock `*this` after the call.
    // `hint` and `size` are ignored.
    IO_Result
    do_on_async_poll_write(Si_Mutex::unique_lock& lock, void* hint, size_t size)
    final;

    // Notifies a full-duplex channel has been closed.
    void
    do_on_async_poll_shutdown(int err)
    final;

  protected:
    // Performs outgoing connecting preparation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    // This function is not called on incoming connections.
    virtual
    void
    do_stream_preconnect_nolock()
      = 0;

    // Performs read operation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    virtual
    IO_Result
    do_stream_read_nolock(void* data, size_t size)
      = 0;

    // Performs write operation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    virtual
    IO_Result
    do_stream_write_nolock(const void* data, size_t size)
      = 0;

    // Performs shutdown preparation.
    // This function is called by the network thread. The current socket will have
    // been locked by its caller. No synchronization is required.
    // This function shall return `io_result_eof` if the shutdown operation has
    // either completed or failed due to some irrecoverable errors.
    virtual
    IO_Result
    do_stream_preshutdown_nolock()
      = 0;

    // Notifies a full-duplex channel has been established.
    // Please mind thread safety, as this function is called by the network thread.
    virtual
    void
    do_on_async_establish()
      = 0;

    // Consumes an incoming packet.
    // Please mind thread safety, as this function is called by the network thread.
    virtual
    void
    do_on_async_receive(void* data, size_t size)
      = 0;

    // Notifies a socket has been closed.
    // Please mind thread safety, as this function is called by the network thread.
    virtual
    void
    do_on_async_shutdown(int err)
      = 0;

    // Initiates a new connection to the specified address.
    void
    do_async_connect(const Socket_Address& addr);

  public:
    // Enqueues some data for writing.
    // This function returns `true` if the data have been queued, or `false` if a
    // shutdown request has been initiated.
    // This function is thread-safe.
    bool
    async_send(const void* data, size_t size);

    // Initiates normal closure of this stream.
    // This function returns `true` if the shutdown request completes immediately,
    // or `false` if there are still data pending. In either case, the socket is
    // considered closed. No further data may be read from or written through it.
    // Note half-closed connections are not supported.
    bool
    async_shutdown()
    noexcept;
  };

}  // namespace poseidon

#endif
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "EffectsMenu.h"

/* system implementation headers */
#include <string>
#include <vector>

/* common implementation headers */
#include "BundleMgr.h"
#include "BZDBCache.h"
#include "TextUtils.h"
#include "FontManager.h"
#include "SceneRenderer.h"

/* local implementation headers */
#include "MainMenu.h"
#include "MainWindow.h"
#include "TrackMarks.h"
#include "HUDDialogStack.h"
#include "HUDuiControl.h"
#include "HUDuiList.h"
#include "HUDuiLabel.h"
#include "effectsRenderer.h"

EffectsMenu::EffectsMenu()
{
  // add controls
  std::vector<HUDuiControl*>& listHUD = getControls();

  // cache font face ID
  int fontFace = MainMenu::getFontFace();

  // the menu label
  HUDuiLabel* label = new HUDuiLabel;
  label->setFontFace(fontFace);
  label->setString("Effects Settings");
  listHUD.push_back(label);

  // the menu options
  HUDuiList* option;
  std::vector<std::string>* options;

  // Rain Scale
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Rain:");
  option->setCallback(callback, (void*)"r");
  options = &option->getList();
  options->push_back(std::string("Off"));
  option->createSlider(10);
  option->update();
  listHUD.push_back(option);

  // The Mirror
  option = new HUDuiList;
  option->setFontFace(fontFace);
  option->setLabel("Mirror:");
  option->setCallback(callback, (void*)"m");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  // Display Treads
  option = new HUDuiList;
  option->setFontFace(fontFace);
  option->setLabel("Display Treads:");
  option->setCallback(callback, (void*)"T");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  // Animated Treads
  option = new HUDuiList;
  option->setFontFace(fontFace);
  option->setLabel("Animated Treads:");
  option->setCallback(callback, (void*)"a");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  // Track Mark Fading Scale
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Track Marks:");
  option->setCallback(callback, (void*)"t");
  options = &option->getList();
  options->push_back(std::string("Off"));
  option->createSlider(10);
  option->update();
  listHUD.push_back(option);

  // Track Mark Culling Type
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Track Mark Culling:");
  option->setCallback(callback, (void*)"c");
  options = &option->getList();
  options->push_back(std::string("None"));
  options->push_back(std::string("Fast"));
  options->push_back(std::string("Best"));
  option->update();
  listHUD.push_back(option);

  // Fancy effects from effectsRenderer
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Fancy Effects:");
  option->setCallback(callback, (void*)"f");
  options = &option->getList();
  options->push_back(std::string("On"));
  options->push_back(std::string("Off"));
  option->update();
  listHUD.push_back(option);

  std::vector<std::string> optbuf;

  // Fancy effects I: Spawn
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Spawn Effect:");
  option->setCallback(callback, (void*)"s");
  options = &option->getList();
  optbuf = EffectsRenderer::instance().getSpawnFlashTypes();
  options->assign(optbuf.begin(), optbuf.end());
  option->update();
  listHUD.push_back(option);

  // Fancy effects II: Death
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Death Effect:");
  option->setCallback(callback, (void*)"d");
  options = &option->getList();
  optbuf = EffectsRenderer::instance().getDeathFlashTypes();
  options->assign(optbuf.begin(), optbuf.end());
  option->update();
  listHUD.push_back(option);

  // Fancy effects III: Shots
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Shot Fired Effect:");
  option->setCallback(callback, (void*)"S");
  options = &option->getList();
  optbuf = EffectsRenderer::instance().getShotFlashTypes();
  options->assign(optbuf.begin(), optbuf.end());
  option->update();
  listHUD.push_back(option);

  // Fancy effects IV: Local shots
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Local Shot Effect:");
  option->setCallback(callback, (void*)"l");
  options = &option->getList();
  options->push_back(std::string("Same as shots"));
  options->push_back(std::string("Disabled"));
  option->update();
  listHUD.push_back(option);

  initNavigation(listHUD, 1, listHUD.size() - 1);
}

EffectsMenu::~EffectsMenu()
{
}

void EffectsMenu::execute()
{
}

void EffectsMenu::resize(int _width, int _height)
{
  HUDDialog::resize(_width, _height);

  // use a big font for title, smaller font for the rest
  const float titleFontSize = (float)_height / 15.0f;
  const float fontSize = (float)_height / 45.0f;
  FontManager &fm = FontManager::instance();

  // reposition title
  std::vector<HUDuiControl*>& listHUD = getControls();
  HUDuiLabel* title = (HUDuiLabel*)listHUD[0];
  title->setFontSize(titleFontSize);
  const float titleWidth =
    fm.getStrLength(MainMenu::getFontFace(), titleFontSize, title->getString());
  const float titleHeight =
    fm.getStrHeight(MainMenu::getFontFace(), titleFontSize, " ");
  float x = 0.5f * ((float)_width - titleWidth);
  float y = (float)_height - titleHeight;
  title->setPosition(x, y);

  // reposition options
  x = 0.5f * (float)_width;
  y -= 0.6f * titleHeight;
  const float h = fm.getStrHeight(MainMenu::getFontFace(), fontSize, " ");
  const int count = listHUD.size();
  int i;
  for (i = 1; i < count; i++) {
    listHUD[i]->setFontSize(fontSize);
    listHUD[i]->setPosition(x, y);
    if ((i == 2) || (i == 4) || (i == 6)) {
      y -= 1.75f * h;
    } else {
      y -= 1.0f * h;
    }
  }

  // load current settings
  i = 1;
  ((HUDuiList*)listHUD[i++])->setIndex(int((BZDB.eval("userRainScale")
					    * 10.0f) + 0.5f));
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("userMirror") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("showTreads") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("animatedTreads") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(int((TrackMarks::getUserFade() * 10.0f)
					   + 0.5f));
  TrackMarks::AirCullStyle style = TrackMarks::getAirCulling();
  if (style == TrackMarks::NoAirCull) {
    ((HUDuiList*)listHUD[i++])->setIndex(0);
  } else if (style != TrackMarks::FullAirCull) {
    ((HUDuiList*)listHUD[i++])->setIndex(1);
  } else {
    ((HUDuiList*)listHUD[i++])->setIndex(2);
  }
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("useFancyEffects") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("spawnEffect")));
  ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("deathEffect")));
  ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("shotEffect")));
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("enableLocalShotEffect") ? 1 : 0);
}

void EffectsMenu::callback(HUDuiControl* w, void* data)
{
  HUDuiList* list = (HUDuiList*)w;

  switch (((const char*)data)[0]) {
    case 'r': {
      int scale = list->getIndex();
      BZDB.setFloat("userRainScale", float(scale) / 10.0f);
      break;
    }
    case 'm': {
      BZDB.set("userMirror", list->getIndex() ? "1" : "0");
      break;
    }
    case 'T': {
      BZDB.set("showTreads", list->getIndex() ? "1" : "0");
      break;
    }
    case 'a': {
      BZDB.set("animatedTreads", list->getIndex() ? "1" : "0");
      RENDERER.setRebuildTanks();
      break;
    }
    case 't': {
      int fade = list->getIndex();
      TrackMarks::setUserFade(float(fade) / 10.0f);
      break;
    }
    case 'c': {
      int culling = list->getIndex();
      if (culling <= 0) {
	TrackMarks::setAirCulling(TrackMarks::NoAirCull);
      } else if (culling == 1) {
	TrackMarks::setAirCulling(TrackMarks::InitAirCull);
      } else {
	TrackMarks::setAirCulling(TrackMarks::FullAirCull);
      }
      break;
    }
    case 'f': {
      BZDB.set("useFancyEffects", list->getIndex() ? "1" : "0");
      break;
    }
    case 's': {
      BZDB.set("spawnEffect", TextUtils::format("%d", list->getIndex()));
      break;
    }
    case 'd': {
      BZDB.set("deathEffect", TextUtils::format("%d", list->getIndex()));
      break;
    }
    case 'S': {
      BZDB.set("shotEffect", TextUtils::format("%d", list->getIndex()));
      break;
    }
    case 'l': {
      BZDB.set("enableLocalShotEffect", list->getIndex() ? "1" : "0");
      break;
    }
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>un-reverse the boolean options<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "EffectsMenu.h"

/* system implementation headers */
#include <string>
#include <vector>

/* common implementation headers */
#include "BundleMgr.h"
#include "BZDBCache.h"
#include "TextUtils.h"
#include "FontManager.h"
#include "SceneRenderer.h"

/* local implementation headers */
#include "MainMenu.h"
#include "MainWindow.h"
#include "TrackMarks.h"
#include "HUDDialogStack.h"
#include "HUDuiControl.h"
#include "HUDuiList.h"
#include "HUDuiLabel.h"
#include "effectsRenderer.h"

EffectsMenu::EffectsMenu()
{
  // add controls
  std::vector<HUDuiControl*>& listHUD = getControls();

  // cache font face ID
  int fontFace = MainMenu::getFontFace();

  // the menu label
  HUDuiLabel* label = new HUDuiLabel;
  label->setFontFace(fontFace);
  label->setString("Effects Settings");
  listHUD.push_back(label);

  // the menu options
  HUDuiList* option;
  std::vector<std::string>* options;

  // Rain Scale
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Rain:");
  option->setCallback(callback, (void*)"r");
  options = &option->getList();
  options->push_back(std::string("Off"));
  option->createSlider(10);
  option->update();
  listHUD.push_back(option);

  // The Mirror
  option = new HUDuiList;
  option->setFontFace(fontFace);
  option->setLabel("Mirror:");
  option->setCallback(callback, (void*)"m");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  // Display Treads
  option = new HUDuiList;
  option->setFontFace(fontFace);
  option->setLabel("Display Treads:");
  option->setCallback(callback, (void*)"T");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  // Animated Treads
  option = new HUDuiList;
  option->setFontFace(fontFace);
  option->setLabel("Animated Treads:");
  option->setCallback(callback, (void*)"a");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  // Track Mark Fading Scale
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Track Marks:");
  option->setCallback(callback, (void*)"t");
  options = &option->getList();
  options->push_back(std::string("Off"));
  option->createSlider(10);
  option->update();
  listHUD.push_back(option);

  // Track Mark Culling Type
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Track Mark Culling:");
  option->setCallback(callback, (void*)"c");
  options = &option->getList();
  options->push_back(std::string("None"));
  options->push_back(std::string("Fast"));
  options->push_back(std::string("Best"));
  option->update();
  listHUD.push_back(option);

  // Fancy effects from effectsRenderer
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("Fancy Effects:");
  option->setCallback(callback, (void*)"f");
  options = &option->getList();
  options->push_back(std::string("Off"));
  options->push_back(std::string("On"));
  option->update();
  listHUD.push_back(option);

  std::vector<std::string> optbuf;

  // Fancy effects I: Spawn
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Spawn Effect:");
  option->setCallback(callback, (void*)"s");
  options = &option->getList();
  optbuf = EffectsRenderer::instance().getSpawnFlashTypes();
  options->assign(optbuf.begin(), optbuf.end());
  option->update();
  listHUD.push_back(option);

  // Fancy effects II: Death
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Death Effect:");
  option->setCallback(callback, (void*)"d");
  options = &option->getList();
  optbuf = EffectsRenderer::instance().getDeathFlashTypes();
  options->assign(optbuf.begin(), optbuf.end());
  option->update();
  listHUD.push_back(option);

  // Fancy effects III: Shots
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Shot Fired Effect:");
  option->setCallback(callback, (void*)"S");
  options = &option->getList();
  optbuf = EffectsRenderer::instance().getShotFlashTypes();
  options->assign(optbuf.begin(), optbuf.end());
  option->update();
  listHUD.push_back(option);

  // Fancy effects IV: Local shots
  option = new HUDuiList;
  option->setFontFace(MainMenu::getFontFace());
  option->setLabel("  Local Shot Effect:");
  option->setCallback(callback, (void*)"l");
  options = &option->getList();
  options->push_back(std::string("Disabled"));
  options->push_back(std::string("Same as shots"));
  option->update();
  listHUD.push_back(option);

  initNavigation(listHUD, 1, listHUD.size() - 1);
}

EffectsMenu::~EffectsMenu()
{
}

void EffectsMenu::execute()
{
}

void EffectsMenu::resize(int _width, int _height)
{
  HUDDialog::resize(_width, _height);

  // use a big font for title, smaller font for the rest
  const float titleFontSize = (float)_height / 15.0f;
  const float fontSize = (float)_height / 45.0f;
  FontManager &fm = FontManager::instance();

  // reposition title
  std::vector<HUDuiControl*>& listHUD = getControls();
  HUDuiLabel* title = (HUDuiLabel*)listHUD[0];
  title->setFontSize(titleFontSize);
  const float titleWidth =
    fm.getStrLength(MainMenu::getFontFace(), titleFontSize, title->getString());
  const float titleHeight =
    fm.getStrHeight(MainMenu::getFontFace(), titleFontSize, " ");
  float x = 0.5f * ((float)_width - titleWidth);
  float y = (float)_height - titleHeight;
  title->setPosition(x, y);

  // reposition options
  x = 0.5f * (float)_width;
  y -= 0.6f * titleHeight;
  const float h = fm.getStrHeight(MainMenu::getFontFace(), fontSize, " ");
  const int count = listHUD.size();
  int i;
  for (i = 1; i < count; i++) {
    listHUD[i]->setFontSize(fontSize);
    listHUD[i]->setPosition(x, y);
    if ((i == 2) || (i == 4) || (i == 6)) {
      y -= 1.75f * h;
    } else {
      y -= 1.0f * h;
    }
  }

  // load current settings
  i = 1;
  ((HUDuiList*)listHUD[i++])->setIndex(int((BZDB.eval("userRainScale")
					    * 10.0f) + 0.5f));
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("userMirror") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("showTreads") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("animatedTreads") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(int((TrackMarks::getUserFade() * 10.0f)
					   + 0.5f));
  TrackMarks::AirCullStyle style = TrackMarks::getAirCulling();
  if (style == TrackMarks::NoAirCull) {
    ((HUDuiList*)listHUD[i++])->setIndex(0);
  } else if (style != TrackMarks::FullAirCull) {
    ((HUDuiList*)listHUD[i++])->setIndex(1);
  } else {
    ((HUDuiList*)listHUD[i++])->setIndex(2);
  }
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("useFancyEffects") ? 1 : 0);
  ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("spawnEffect")));
  ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("deathEffect")));
  ((HUDuiList*)listHUD[i++])->setIndex(static_cast<int>(BZDB.eval("shotEffect")));
  ((HUDuiList*)listHUD[i++])->setIndex(BZDB.isTrue("enableLocalShotEffect") ? 1 : 0);
}

void EffectsMenu::callback(HUDuiControl* w, void* data)
{
  HUDuiList* list = (HUDuiList*)w;

  switch (((const char*)data)[0]) {
    case 'r': {
      int scale = list->getIndex();
      BZDB.setFloat("userRainScale", float(scale) / 10.0f);
      break;
    }
    case 'm': {
      BZDB.set("userMirror", list->getIndex() ? "1" : "0");
      break;
    }
    case 'T': {
      BZDB.set("showTreads", list->getIndex() ? "1" : "0");
      break;
    }
    case 'a': {
      BZDB.set("animatedTreads", list->getIndex() ? "1" : "0");
      RENDERER.setRebuildTanks();
      break;
    }
    case 't': {
      int fade = list->getIndex();
      TrackMarks::setUserFade(float(fade) / 10.0f);
      break;
    }
    case 'c': {
      int culling = list->getIndex();
      if (culling <= 0) {
	TrackMarks::setAirCulling(TrackMarks::NoAirCull);
      } else if (culling == 1) {
	TrackMarks::setAirCulling(TrackMarks::InitAirCull);
      } else {
	TrackMarks::setAirCulling(TrackMarks::FullAirCull);
      }
      break;
    }
    case 'f': {
      BZDB.set("useFancyEffects", list->getIndex() ? "1" : "0");
      break;
    }
    case 's': {
      BZDB.set("spawnEffect", TextUtils::format("%d", list->getIndex()));
      break;
    }
    case 'd': {
      BZDB.set("deathEffect", TextUtils::format("%d", list->getIndex()));
      break;
    }
    case 'S': {
      BZDB.set("shotEffect", TextUtils::format("%d", list->getIndex()));
      break;
    }
    case 'l': {
      BZDB.set("enableLocalShotEffect", list->getIndex() ? "1" : "0");
      break;
    }
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>