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

#include "profilemanager.h"

#include "profile.h"
#include "profileconfigwidget.h"
#include "profilemanagerconfigwidget.h"
#include "project.h"

#include <coreplugin/icore.h>

#include <extensionsystem/pluginmanager.h>

#include <utils/persistentsettings.h>
#include <utils/environment.h>

#include <QCoreApplication>
#include <QDir>
#include <QSettings>

#include <QFormLayout>
#include <QLabel>
#include <QMainWindow>

static const char PROFILE_DATA_KEY[] = "Profile.";
static const char PROFILE_COUNT_KEY[] = "Profile.Count";
static const char PROFILE_FILE_VERSION_KEY[] = "Version";
static const char PROFILE_DEFAULT_KEY[] = "Profile.Default";
static const char PROFILE_FILENAME[] = "/qtcreator/profiles.xml";

using Utils::PersistentSettingsWriter;
using Utils::PersistentSettingsReader;

static QString settingsFileName()
{
    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
    QFileInfo settingsLocation(pm->settings()->fileName());
    return settingsLocation.absolutePath() + QLatin1String(PROFILE_FILENAME);
}

namespace ProjectExplorer {

ProfileManager *ProfileManager::m_instance = 0;

namespace Internal {

// --------------------------------------------------------------------------
// ProfileManagerPrivate:
// --------------------------------------------------------------------------

class ProfileManagerPrivate
{
public:
    ProfileManagerPrivate();
    ~ProfileManagerPrivate();
    QList<Task> validateProfile(Profile *p) const;

    Profile *m_defaultProfile;
    bool m_initialized;
    QList<ProfileInformation *> m_informationList;
    QList<Profile *> m_profileList;
};

ProfileManagerPrivate::ProfileManagerPrivate()
    : m_defaultProfile(0), m_initialized(false)
{ }

ProfileManagerPrivate::~ProfileManagerPrivate()
{
}

QList<Task> ProfileManagerPrivate::validateProfile(Profile *p) const
{
    Q_ASSERT(p);
    QList<Task> result;
    bool hasError = false;
    foreach (ProfileInformation *pi, m_informationList) {
        QList<Task> tmp = pi->validate(p);
        foreach (const Task &t, tmp)
            if (t.type == Task::Error)
                hasError = true;
        result << tmp;
    }
    p->setValid(!hasError);
    return result;
}

} // namespace Internal

// --------------------------------------------------------------------------
// ProfileManager:
// --------------------------------------------------------------------------

ProfileManager *ProfileManager::instance()
{
    return m_instance;
}

ProfileManager::ProfileManager(QObject *parent) :
    QObject(parent),
    d(new Internal::ProfileManagerPrivate())
{
    Q_ASSERT(!m_instance);
    m_instance = this;

    connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
            this, SLOT(saveProfiles()));

    connect(this, SIGNAL(profileAdded(ProjectExplorer::Profile*)),
            this, SIGNAL(profilesChanged()));
    connect(this, SIGNAL(profileRemoved(ProjectExplorer::Profile*)),
            this, SIGNAL(profilesChanged()));
    connect(this, SIGNAL(profileUpdated(ProjectExplorer::Profile*)),
            this, SIGNAL(profilesChanged()));
}

void ProfileManager::restoreProfiles()
{
    QList<Profile *> stsToRegister;
    QList<Profile *> stsToCheck;

    // read all profiles from SDK
    QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
    ProfileList system = restoreProfiles(systemSettingsFile.absolutePath() + QLatin1String(PROFILE_FILENAME));
    QList<Profile *> readSts = system.profiles;
    // make sure we mark these as autodetected!
    foreach (Profile *p, readSts)
        p->setAutoDetected(true);

    stsToRegister = readSts; // SDK profiles are always considered to be up-to-date, so no need to
                             // recheck them.

    // read all profile chains from user file
    ProfileList userProfiles = restoreProfiles(settingsFileName());
    readSts = userProfiles.profiles;

    foreach (Profile *p, readSts) {
        if (p->isAutoDetected())
            stsToCheck.append(p);
        else
            stsToRegister.append(p);
    }
    readSts.clear();

    // Then auto create profiles:
    QList<Profile *> detectedSts;
    Profile *defaultProfile = new Profile; // One profile using default values
    defaultProfile->setDisplayName(tr("Desktop"));
    defaultProfile->setAutoDetected(true);
    defaultProfile->setIconPath(QLatin1String(":///DESKTOP///"));

    detectedSts << defaultProfile;

    // Find/update autodetected profiles:
    Profile *toStore = 0;
    foreach (Profile *currentDetected, detectedSts) {
        toStore = currentDetected;

        // Check whether we had this profile stored and prefer the old one with the old id:
        for (int i = 0; i < stsToCheck.count(); ++i) {
            if (*(stsToCheck.at(i)) == *currentDetected) {
                toStore = stsToCheck.at(i);
                stsToCheck.removeAt(i);
                delete currentDetected;
                break;
            }
        }
        addProfile(toStore);
    }

    // Delete all loaded autodetected profiles that were not rediscovered:
    qDeleteAll(stsToCheck);

    // Store manual tool chains
    foreach (Profile *p, stsToRegister)
        addProfile(p);

    Profile *p = find(userProfiles.defaultProfile);
    if (p)
        setDefaultProfile(p);
}

ProfileManager::~ProfileManager()
{
    // Clean out profile information to avoid calling them during deregistration:
    qDeleteAll(d->m_informationList);
    qDeleteAll(d->m_profileList);
    delete d;
    m_instance = 0;
}

void ProfileManager::saveProfiles()
{
    PersistentSettingsWriter writer;
    writer.saveValue(QLatin1String(PROFILE_FILE_VERSION_KEY), 1);

    int count = 0;
    foreach (Profile *p, profiles()) {
        QVariantMap tmp = p->toMap();
        if (tmp.isEmpty())
            continue;
        writer.saveValue(QString::fromLatin1(PROFILE_DATA_KEY) + QString::number(count), tmp);
        ++count;
    }
    writer.saveValue(QLatin1String(PROFILE_COUNT_KEY), count);
    writer.saveValue(QLatin1String(PROFILE_DEFAULT_KEY),
                     d->m_defaultProfile ? QString::fromLatin1(d->m_defaultProfile->id().name()) : QString());
    writer.save(settingsFileName(), QLatin1String("QtCreatorProfiles"), Core::ICore::mainWindow());
}

bool greaterPriority(ProfileInformation *a, ProfileInformation *b)
{
    return a->priority() > b->priority();
}

void ProfileManager::registerProfileInformation(ProfileInformation *pi)
{
    QList<ProfileInformation *>::iterator it
            = qLowerBound(d->m_informationList.begin(), d->m_informationList.end(), pi, greaterPriority);
    d->m_informationList.insert(it, pi);

    connect(pi, SIGNAL(validationNeeded()), this, SLOT(validateProfiles()));

    if (!d->m_initialized)
        return;

    foreach (Profile *p, profiles()) {
        if (!p->hasValue(pi->dataId()))
            p->setValue(pi->dataId(), pi->defaultValue(p));
    }

    return;
}

void ProfileManager::deregisterProfileInformation(ProfileInformation *pi)
{
    Q_ASSERT(d->m_informationList.contains(pi));
    d->m_informationList.removeAll(pi);
    delete pi;
}

ProfileManager::ProfileList ProfileManager::restoreProfiles(const QString &fileName)
{
    ProfileList result;

    PersistentSettingsReader reader;
    if (!reader.load(fileName))
        return result;
    QVariantMap data = reader.restoreValues();

    // Check version:
    int version = data.value(QLatin1String(PROFILE_FILE_VERSION_KEY), 0).toInt();
    if (version < 1)
        return result;

    const int count = data.value(QLatin1String(PROFILE_COUNT_KEY), 0).toInt();
    for (int i = 0; i < count; ++i) {
        const QString key = QString::fromLatin1(PROFILE_DATA_KEY) + QString::number(i);
        if (!data.contains(key))
            break;

        const QVariantMap stMap = data.value(key).toMap();

        Profile *p = new Profile;
        if (p->fromMap(stMap)) {
            result.profiles.append(p);
        } else {
            delete p;
            qWarning("Warning: Unable to restore profiles stored in %s at position %d.",
                     qPrintable(QDir::toNativeSeparators(fileName)), i);
        }
    }
    const QString defaultId = data.value(QLatin1String(PROFILE_DEFAULT_KEY)).toString();
    if (defaultId.isEmpty())
        return result;

    const Core::Id id = Core::Id(defaultId);
    foreach (Profile *i, result.profiles) {
        if (i->id() == id) {
            result.defaultProfile = id;
            break;
        }
    }
    return result;
}

QList<Profile *> ProfileManager::profiles(const ProfileMatcher *m) const
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        const_cast<ProfileManager *>(this)->restoreProfiles();
    }

    QList<Profile *> result;
    foreach (Profile *p, d->m_profileList) {
        if (!m || m->matches(p))
            result.append(p);
    }
    return result;
}

Profile *ProfileManager::find(const Core::Id &id) const
{
    if (!id.isValid())
        return 0;

    foreach (Profile *p, profiles()) {
        if (p->id() == id)
            return p;
    }
    return 0;
}

Profile *ProfileManager::find(const ProfileMatcher *m) const
{
    QList<Profile *> matched = profiles(m);
    return matched.isEmpty() ? 0 : matched.first();
}

Profile *ProfileManager::defaultProfile()
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        restoreProfiles();
    }
    return d->m_defaultProfile;
}

QList<ProfileInformation *> ProfileManager::profileInformation() const
{
    return d->m_informationList;
}

ProfileConfigWidget *ProfileManager::createConfigWidget(Profile *p) const
{
    if (!p)
        return 0;

    Internal::ProfileManagerConfigWidget *result = new Internal::ProfileManagerConfigWidget(p);
    foreach (ProfileInformation *pi, d->m_informationList)
        result->addConfigWidget(pi->createConfigWidget(p));

    return result;
}

void ProfileManager::notifyAboutUpdate(ProjectExplorer::Profile *p)
{
    if (!p || !profiles().contains(p))
        return;
    d->validateProfile(p);
    emit profileUpdated(p);
}

bool ProfileManager::registerProfile(ProjectExplorer::Profile *p)
{
    if (!p)
        return true;
    foreach (Profile *current, profiles()) {
        if (p == current)
            return false;
    }

    // Make name unique:
    QStringList names;
    foreach (Profile *tmp, profiles())
        names << tmp->displayName();
    p->setDisplayName(Project::makeUnique(p->displayName(), names));

    // make sure we have all the information in our profiles:
    foreach (ProfileInformation *pi, d->m_informationList) {
        if (!p->hasValue(pi->dataId()))
            p->setValue(pi->dataId(), pi->defaultValue(p));
    }

    addProfile(p);
    emit profileAdded(p);
    return true;
}

void ProfileManager::deregisterProfile(Profile *p)
{
    if (!p || !profiles().contains(p))
        return;
    d->m_profileList.removeOne(p);
    if (d->m_defaultProfile == p) {
        QList<Profile *> stList = profiles();
        Profile *newDefault = 0;
        foreach (Profile *cur, stList) {
            if (cur->isValid()) {
                newDefault = cur;
                break;
            }
        }
        setDefaultProfile(newDefault);
    }
    emit profileRemoved(p);
    delete p;
}

QList<Task> ProfileManager::validateProfile(Profile *p)
{
    QList<Task> result = d->validateProfile(p);
    qSort(result);
    return result;
}

void ProfileManager::setDefaultProfile(Profile *p)
{
    if (d->m_defaultProfile == p)
        return;
    if (p && !profiles().contains(p))
        return;
    d->m_defaultProfile = p;
    emit defaultProfileChanged();
}

void ProfileManager::validateProfiles()
{
    foreach (Profile *p, profiles())
        d->validateProfile(p);
}

void ProfileManager::addProfile(Profile *p)
{
    if (!p)
        return;
    d->validateProfile(p);
    d->m_profileList.append(p);
    if (!d->m_defaultProfile ||
            (!d->m_defaultProfile->isValid() && p->isValid()))
        setDefaultProfile(p);
}

void ProfileInformation::addToEnvironment(const Profile *p, Utils::Environment &env) const
{
    Q_UNUSED(p);
    Q_UNUSED(env);
}

} // namespace ProjectExplorer
<commit_msg>ProfileManager: Create the desktop profile as manual<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "profilemanager.h"

#include "profile.h"
#include "profileconfigwidget.h"
#include "profilemanagerconfigwidget.h"
#include "project.h"

#include <coreplugin/icore.h>

#include <extensionsystem/pluginmanager.h>

#include <utils/persistentsettings.h>
#include <utils/environment.h>

#include <QCoreApplication>
#include <QDir>
#include <QSettings>

#include <QFormLayout>
#include <QLabel>
#include <QMainWindow>

static const char PROFILE_DATA_KEY[] = "Profile.";
static const char PROFILE_COUNT_KEY[] = "Profile.Count";
static const char PROFILE_FILE_VERSION_KEY[] = "Version";
static const char PROFILE_DEFAULT_KEY[] = "Profile.Default";
static const char PROFILE_FILENAME[] = "/qtcreator/profiles.xml";

using Utils::PersistentSettingsWriter;
using Utils::PersistentSettingsReader;

static QString settingsFileName()
{
    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
    QFileInfo settingsLocation(pm->settings()->fileName());
    return settingsLocation.absolutePath() + QLatin1String(PROFILE_FILENAME);
}

namespace ProjectExplorer {

ProfileManager *ProfileManager::m_instance = 0;

namespace Internal {

// --------------------------------------------------------------------------
// ProfileManagerPrivate:
// --------------------------------------------------------------------------

class ProfileManagerPrivate
{
public:
    ProfileManagerPrivate();
    ~ProfileManagerPrivate();
    QList<Task> validateProfile(Profile *p) const;

    Profile *m_defaultProfile;
    bool m_initialized;
    QList<ProfileInformation *> m_informationList;
    QList<Profile *> m_profileList;
};

ProfileManagerPrivate::ProfileManagerPrivate()
    : m_defaultProfile(0), m_initialized(false)
{ }

ProfileManagerPrivate::~ProfileManagerPrivate()
{
}

QList<Task> ProfileManagerPrivate::validateProfile(Profile *p) const
{
    Q_ASSERT(p);
    QList<Task> result;
    bool hasError = false;
    foreach (ProfileInformation *pi, m_informationList) {
        QList<Task> tmp = pi->validate(p);
        foreach (const Task &t, tmp)
            if (t.type == Task::Error)
                hasError = true;
        result << tmp;
    }
    p->setValid(!hasError);
    return result;
}

} // namespace Internal

// --------------------------------------------------------------------------
// ProfileManager:
// --------------------------------------------------------------------------

ProfileManager *ProfileManager::instance()
{
    return m_instance;
}

ProfileManager::ProfileManager(QObject *parent) :
    QObject(parent),
    d(new Internal::ProfileManagerPrivate())
{
    Q_ASSERT(!m_instance);
    m_instance = this;

    connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
            this, SLOT(saveProfiles()));

    connect(this, SIGNAL(profileAdded(ProjectExplorer::Profile*)),
            this, SIGNAL(profilesChanged()));
    connect(this, SIGNAL(profileRemoved(ProjectExplorer::Profile*)),
            this, SIGNAL(profilesChanged()));
    connect(this, SIGNAL(profileUpdated(ProjectExplorer::Profile*)),
            this, SIGNAL(profilesChanged()));
}

void ProfileManager::restoreProfiles()
{
    QList<Profile *> stsToRegister;
    QList<Profile *> stsToCheck;

    // read all profiles from SDK
    QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
    ProfileList system = restoreProfiles(systemSettingsFile.absolutePath() + QLatin1String(PROFILE_FILENAME));
    QList<Profile *> readSts = system.profiles;
    // make sure we mark these as autodetected!
    foreach (Profile *p, readSts)
        p->setAutoDetected(true);

    stsToRegister = readSts; // SDK profiles are always considered to be up-to-date, so no need to
                             // recheck them.

    // read all profile chains from user file
    ProfileList userProfiles = restoreProfiles(settingsFileName());
    readSts = userProfiles.profiles;

    foreach (Profile *p, readSts) {
        if (p->isAutoDetected())
            stsToCheck.append(p);
        else
            stsToRegister.append(p);
    }
    readSts.clear();

    // Then auto create profiles:
    QList<Profile *> detectedSts;

    // Find/update autodetected profiles:
    Profile *toStore = 0;
    foreach (Profile *currentDetected, detectedSts) {
        toStore = currentDetected;

        // Check whether we had this profile stored and prefer the old one with the old id:
        for (int i = 0; i < stsToCheck.count(); ++i) {
            if (*(stsToCheck.at(i)) == *currentDetected) {
                toStore = stsToCheck.at(i);
                stsToCheck.removeAt(i);
                delete currentDetected;
                break;
            }
        }
        addProfile(toStore);
    }

    // Delete all loaded autodetected profiles that were not rediscovered:
    qDeleteAll(stsToCheck);

    // Store manual profiles
    foreach (Profile *p, stsToRegister)
        addProfile(p);

    if (profiles().isEmpty()) {
        Profile *defaultProfile = new Profile; // One profile using default values
        defaultProfile->setDisplayName(tr("Desktop"));
        defaultProfile->setAutoDetected(false);
        defaultProfile->setIconPath(QLatin1String(":///DESKTOP///"));

        addProfile(defaultProfile);
    }

    Profile *p = find(userProfiles.defaultProfile);
    if (p)
        setDefaultProfile(p);
}

ProfileManager::~ProfileManager()
{
    // Clean out profile information to avoid calling them during deregistration:
    qDeleteAll(d->m_informationList);
    qDeleteAll(d->m_profileList);
    delete d;
    m_instance = 0;
}

void ProfileManager::saveProfiles()
{
    PersistentSettingsWriter writer;
    writer.saveValue(QLatin1String(PROFILE_FILE_VERSION_KEY), 1);

    int count = 0;
    foreach (Profile *p, profiles()) {
        QVariantMap tmp = p->toMap();
        if (tmp.isEmpty())
            continue;
        writer.saveValue(QString::fromLatin1(PROFILE_DATA_KEY) + QString::number(count), tmp);
        ++count;
    }
    writer.saveValue(QLatin1String(PROFILE_COUNT_KEY), count);
    writer.saveValue(QLatin1String(PROFILE_DEFAULT_KEY),
                     d->m_defaultProfile ? QString::fromLatin1(d->m_defaultProfile->id().name()) : QString());
    writer.save(settingsFileName(), QLatin1String("QtCreatorProfiles"), Core::ICore::mainWindow());
}

bool greaterPriority(ProfileInformation *a, ProfileInformation *b)
{
    return a->priority() > b->priority();
}

void ProfileManager::registerProfileInformation(ProfileInformation *pi)
{
    QList<ProfileInformation *>::iterator it
            = qLowerBound(d->m_informationList.begin(), d->m_informationList.end(), pi, greaterPriority);
    d->m_informationList.insert(it, pi);

    connect(pi, SIGNAL(validationNeeded()), this, SLOT(validateProfiles()));

    if (!d->m_initialized)
        return;

    foreach (Profile *p, profiles()) {
        if (!p->hasValue(pi->dataId()))
            p->setValue(pi->dataId(), pi->defaultValue(p));
    }

    return;
}

void ProfileManager::deregisterProfileInformation(ProfileInformation *pi)
{
    Q_ASSERT(d->m_informationList.contains(pi));
    d->m_informationList.removeAll(pi);
    delete pi;
}

ProfileManager::ProfileList ProfileManager::restoreProfiles(const QString &fileName)
{
    ProfileList result;

    PersistentSettingsReader reader;
    if (!reader.load(fileName))
        return result;
    QVariantMap data = reader.restoreValues();

    // Check version:
    int version = data.value(QLatin1String(PROFILE_FILE_VERSION_KEY), 0).toInt();
    if (version < 1)
        return result;

    const int count = data.value(QLatin1String(PROFILE_COUNT_KEY), 0).toInt();
    for (int i = 0; i < count; ++i) {
        const QString key = QString::fromLatin1(PROFILE_DATA_KEY) + QString::number(i);
        if (!data.contains(key))
            break;

        const QVariantMap stMap = data.value(key).toMap();

        Profile *p = new Profile;
        if (p->fromMap(stMap)) {
            result.profiles.append(p);
        } else {
            delete p;
            qWarning("Warning: Unable to restore profiles stored in %s at position %d.",
                     qPrintable(QDir::toNativeSeparators(fileName)), i);
        }
    }
    const QString defaultId = data.value(QLatin1String(PROFILE_DEFAULT_KEY)).toString();
    if (defaultId.isEmpty())
        return result;

    const Core::Id id = Core::Id(defaultId);
    foreach (Profile *i, result.profiles) {
        if (i->id() == id) {
            result.defaultProfile = id;
            break;
        }
    }
    return result;
}

QList<Profile *> ProfileManager::profiles(const ProfileMatcher *m) const
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        const_cast<ProfileManager *>(this)->restoreProfiles();
    }

    QList<Profile *> result;
    foreach (Profile *p, d->m_profileList) {
        if (!m || m->matches(p))
            result.append(p);
    }
    return result;
}

Profile *ProfileManager::find(const Core::Id &id) const
{
    if (!id.isValid())
        return 0;

    foreach (Profile *p, profiles()) {
        if (p->id() == id)
            return p;
    }
    return 0;
}

Profile *ProfileManager::find(const ProfileMatcher *m) const
{
    QList<Profile *> matched = profiles(m);
    return matched.isEmpty() ? 0 : matched.first();
}

Profile *ProfileManager::defaultProfile()
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        restoreProfiles();
    }
    return d->m_defaultProfile;
}

QList<ProfileInformation *> ProfileManager::profileInformation() const
{
    return d->m_informationList;
}

ProfileConfigWidget *ProfileManager::createConfigWidget(Profile *p) const
{
    if (!p)
        return 0;

    Internal::ProfileManagerConfigWidget *result = new Internal::ProfileManagerConfigWidget(p);
    foreach (ProfileInformation *pi, d->m_informationList)
        result->addConfigWidget(pi->createConfigWidget(p));

    return result;
}

void ProfileManager::notifyAboutUpdate(ProjectExplorer::Profile *p)
{
    if (!p || !profiles().contains(p))
        return;
    d->validateProfile(p);
    emit profileUpdated(p);
}

bool ProfileManager::registerProfile(ProjectExplorer::Profile *p)
{
    if (!p)
        return true;
    foreach (Profile *current, profiles()) {
        if (p == current)
            return false;
    }

    // Make name unique:
    QStringList names;
    foreach (Profile *tmp, profiles())
        names << tmp->displayName();
    p->setDisplayName(Project::makeUnique(p->displayName(), names));

    // make sure we have all the information in our profiles:
    foreach (ProfileInformation *pi, d->m_informationList) {
        if (!p->hasValue(pi->dataId()))
            p->setValue(pi->dataId(), pi->defaultValue(p));
    }

    addProfile(p);
    emit profileAdded(p);
    return true;
}

void ProfileManager::deregisterProfile(Profile *p)
{
    if (!p || !profiles().contains(p))
        return;
    d->m_profileList.removeOne(p);
    if (d->m_defaultProfile == p) {
        QList<Profile *> stList = profiles();
        Profile *newDefault = 0;
        foreach (Profile *cur, stList) {
            if (cur->isValid()) {
                newDefault = cur;
                break;
            }
        }
        setDefaultProfile(newDefault);
    }
    emit profileRemoved(p);
    delete p;
}

QList<Task> ProfileManager::validateProfile(Profile *p)
{
    QList<Task> result = d->validateProfile(p);
    qSort(result);
    return result;
}

void ProfileManager::setDefaultProfile(Profile *p)
{
    if (d->m_defaultProfile == p)
        return;
    if (p && !profiles().contains(p))
        return;
    d->m_defaultProfile = p;
    emit defaultProfileChanged();
}

void ProfileManager::validateProfiles()
{
    foreach (Profile *p, profiles())
        d->validateProfile(p);
}

void ProfileManager::addProfile(Profile *p)
{
    if (!p)
        return;
    d->validateProfile(p);
    d->m_profileList.append(p);
    if (!d->m_defaultProfile ||
            (!d->m_defaultProfile->isValid() && p->isValid()))
        setDefaultProfile(p);
}

void ProfileInformation::addToEnvironment(const Profile *p, Utils::Environment &env) const
{
    Q_UNUSED(p);
    Q_UNUSED(env);
}

} // namespace ProjectExplorer
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "MapQuestRunner.h"

#include "MarbleAbstractRunner.h"
#include "MarbleDebug.h"
#include "MarbleLocale.h"
#include "GeoDataDocument.h"
#include "GeoDataPlacemark.h"
#include "GeoDataExtendedData.h"
#include "TinyWebBrowser.h"
#include "routing/Maneuver.h"

#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QUrl>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtXml/QDomDocument>

namespace Marble
{

MapQuestRunner::MapQuestRunner( QObject *parent ) :
    MarbleAbstractRunner( parent ),
    m_networkAccessManager( new QNetworkAccessManager( this ) )
{
    connect( m_networkAccessManager, SIGNAL( finished( QNetworkReply * ) ),
             this, SLOT( retrieveData( QNetworkReply * ) ) );
}

MapQuestRunner::~MapQuestRunner()
{
    // nothing to do
}

GeoDataFeature::GeoDataVisualCategory MapQuestRunner::category() const
{
    return GeoDataFeature::OsmSite;
}

void MapQuestRunner::retrieveRoute( const RouteRequest *route )
{
    if ( route->size() < 2 ) {
        return;
    }

    QHash<QString, QVariant> settings = route->routingProfile().pluginSettings()["mapquest"];

    QString url = "http://open.mapquestapi.com/directions/v0/route?callback=renderAdvancedNarrative&outFormat=xml&narrativeType=text&shapeFormat=raw&generalize=0";
    GeoDataCoordinates::Unit const degree = GeoDataCoordinates::Degree;
    append( &url, "from", QString::number( route->source().latitude( degree ), 'f', 6 ) + "," + QString::number( route->source().longitude( degree ), 'f', 6 ) );
    for ( int i=1; i<route->size(); ++i ) {
        append( &url, "to", QString::number( route->at( i ).latitude( degree ), 'f', 6 ) + "," + QString::number( route->at( i ).longitude( degree ), 'f', 6 ) );
    }

    QString const unit = MarbleGlobal::getInstance()->locale()->measurementSystem() == QLocale::MetricSystem ? "k" : "m";
    append( &url, "units", unit );

    if ( settings["noMotorways"].toInt() ) {
        append( &url, "avoids", "Limited Access" );
    }
    if ( settings["noTollroads"].toInt() ) {
        append( &url, "avoids", "Toll road" );
    }
    if ( settings["noFerries"].toInt() ) {
        append( &url, "avoids", "Ferry" );
    }

    if ( !settings["preference"].toString().isEmpty() ) {
        append( &url, "routeType", settings["preference"].toString() );
    }

    QNetworkReply *reply = m_networkAccessManager->get( QNetworkRequest( QUrl( url ) ) );
    connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ),
             this, SLOT( handleError( QNetworkReply::NetworkError ) ) );

    QEventLoop eventLoop;

    connect( this, SIGNAL( routeCalculated( GeoDataDocument* ) ),
             &eventLoop, SLOT( quit() ) );

    eventLoop.exec();
}

void MapQuestRunner::retrieveData( QNetworkReply *reply )
{
    if ( reply->isFinished() ) {
        QByteArray data = reply->readAll();
        reply->deleteLater();
        //mDebug() << "Download completed: " << data;
        GeoDataDocument* document = parse( data );

        if ( !document ) {
            mDebug() << "Failed to parse the downloaded route data" << data;
        }

        emit routeCalculated( document );
    }
}

void MapQuestRunner::handleError( QNetworkReply::NetworkError error )
{
    mDebug() << " Error when retrieving mapquest.org route: " << error;
}

void MapQuestRunner::append(QString *input, const QString &key, const QString &value)
{
    *input += "&" + key + "=" + value;
}

int MapQuestRunner::maneuverType( int mapQuestId ) const
{
    /** @todo FIXME: review 10, 11 */
    switch( mapQuestId ) {
    case 0: return Maneuver::Straight ; // straight
    case 1: return Maneuver::SlightRight ; // slight right
    case 2: return Maneuver::Right ; // right
    case 3: return Maneuver::SharpRight ; // sharp right
    case 4: return Maneuver::TurnAround ; // reverse
    case 5: return Maneuver::SharpLeft ; // sharp left
    case 6: return Maneuver::Left ; // left
    case 7: return Maneuver::SlightLeft ; // slight left
    case 8: return Maneuver::TurnAround ; // right u-turn
    case 9: return Maneuver::TurnAround ; // left u-turn
    case 10: return Maneuver::Merge ; // right merge
    case 11: return Maneuver::Merge ; // left merge
    case 12: return Maneuver::Merge ; // right on ramp
    case 13: return Maneuver::Merge ; // left on ramp
    case 14: return Maneuver::ExitRight ; // right off ramp
    case 15: return Maneuver::ExitLeft ; // left off ramp
    case 16: return Maneuver::Right ; // right fork
    case 17: return Maneuver::Left ; // left fork
    case 18: return Maneuver::Continue ; // straight fork
    }

    return Maneuver::Unknown;
}

GeoDataDocument* MapQuestRunner::parse( const QByteArray &content ) const
{
    QDomDocument xml;
    if ( !xml.setContent( content ) ) {
        mDebug() << "Cannot parse xml file with routing instructions.";
        return 0;
    }

    // mDebug() << xml.toString(2);
    QDomElement root = xml.documentElement();

    GeoDataDocument* result = new GeoDataDocument();
    result->setName( "MapQuest" );
    GeoDataPlacemark* routePlacemark = new GeoDataPlacemark;
    routePlacemark->setName( "Route" );

    GeoDataLineString* routeWaypoints = new GeoDataLineString;
    QDomNodeList shapePoints = root.elementsByTagName( "shapePoints" );
    if ( shapePoints.size() == 1 ) {
        QDomNodeList geometry = shapePoints.at( 0 ).toElement().elementsByTagName( "latLng" );
        for ( int i=0; i<geometry.size(); ++i ) {
            double const lat = geometry.item( i ).namedItem( "lat" ).toElement().text().toDouble();
            double const lon = geometry.item( i ).namedItem( "lng" ).toElement().text().toDouble();
            GeoDataCoordinates const position( lon, lat, 0.0, GeoDataCoordinates::Degree );
            routeWaypoints->append( position );
        }
    }
    routePlacemark->setGeometry( routeWaypoints );

    QString name = "%1 %2 (MapQuest)";
    QString unit = "m";
    qreal length = routeWaypoints->length( EARTH_RADIUS );
    if (length >= 1000) {
        length /= 1000.0;
        unit = "km";
    }
    result->setName( name.arg( length, 0, 'f', 1 ).arg( unit ) );
    result->append( routePlacemark );

    QMap<int,int> mapping;
    QDomNodeList maneuvers = root.elementsByTagName( "maneuverIndexes" );
    if ( maneuvers.size() == 1 ) {
        maneuvers = maneuvers.at( 0 ).childNodes();
        for ( int i=0; i<maneuvers.size(); ++i ) {
            mapping[i] = maneuvers.at( i ).toElement().text().toInt();
            if ( mapping[i] == routeWaypoints->size() ) {
                --mapping[i];
            }
        }
    }

    QDomNodeList instructions = root.elementsByTagName( "maneuver" );
    unsigned int const lastInstruction = qMax<int>( 0, instructions.length()-1 ); // ignore the last 'Welcome to xy' instruction
    for ( unsigned int i = 0; i < lastInstruction; ++i ) {
        QDomElement node = instructions.item( i ).toElement();

        QDomNodeList maneuver = node.elementsByTagName( "turnType" );
        QDomNodeList textNodes = node.elementsByTagName( "narrative" );
        QDomNodeList points = node.elementsByTagName( "startPoint" );
        QDomNodeList streets = node.elementsByTagName( "streets" );

        Q_ASSERT( mapping.contains( i ) );
        if ( textNodes.size() == 1 && maneuver.size() == 1 && points.size() == 1 && mapping.contains( i ) ) {
            GeoDataPlacemark* instruction = new GeoDataPlacemark;
            instruction->setName( textNodes.at( 0 ).toElement().text() );

            GeoDataExtendedData extendedData;
            GeoDataData turnType;
            turnType.setName( "turnType" );
            turnType.setValue( maneuverType( maneuver.at( 0 ).toElement().text().toInt() ) );
            extendedData.addValue( turnType );
            if ( streets.size() == 1 ) {
                GeoDataData roadName;
                roadName.setName( "roadName" );
                roadName.setValue( streets.at( 0 ).toElement().text() );
                extendedData.addValue( roadName );
            }
            instruction->setExtendedData( extendedData );

            int const start = mapping[i];
            int const end = mapping.contains(i+1) ? mapping[i+1] : routeWaypoints->size()-1;
            if ( start >= 0 && start < routeWaypoints->size() && end < routeWaypoints->size() ) {
                instruction->setName( textNodes.item( 0 ).toElement().text() );
                GeoDataLineString *lineString = new GeoDataLineString;
                for ( int j=start; j<=end; ++j ) {
                    *lineString << GeoDataCoordinates( routeWaypoints->at( j ).longitude(), routeWaypoints->at( j ).latitude() );
                }

                if ( !lineString->isEmpty() ) {
                    instruction->setGeometry( lineString );
                    result->append( instruction );
                }
            }
        }
    }

    return result;
}

} // namespace Marble

#include "MapQuestRunner.moc"
<commit_msg>delete routing document when it is empty<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "MapQuestRunner.h"

#include "MarbleAbstractRunner.h"
#include "MarbleDebug.h"
#include "MarbleLocale.h"
#include "GeoDataDocument.h"
#include "GeoDataPlacemark.h"
#include "GeoDataExtendedData.h"
#include "TinyWebBrowser.h"
#include "routing/Maneuver.h"

#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QUrl>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtXml/QDomDocument>

namespace Marble
{

MapQuestRunner::MapQuestRunner( QObject *parent ) :
    MarbleAbstractRunner( parent ),
    m_networkAccessManager( new QNetworkAccessManager( this ) )
{
    connect( m_networkAccessManager, SIGNAL( finished( QNetworkReply * ) ),
             this, SLOT( retrieveData( QNetworkReply * ) ) );
}

MapQuestRunner::~MapQuestRunner()
{
    // nothing to do
}

GeoDataFeature::GeoDataVisualCategory MapQuestRunner::category() const
{
    return GeoDataFeature::OsmSite;
}

void MapQuestRunner::retrieveRoute( const RouteRequest *route )
{
    if ( route->size() < 2 ) {
        return;
    }

    QHash<QString, QVariant> settings = route->routingProfile().pluginSettings()["mapquest"];

    QString url = "http://open.mapquestapi.com/directions/v0/route?callback=renderAdvancedNarrative&outFormat=xml&narrativeType=text&shapeFormat=raw&generalize=0";
    GeoDataCoordinates::Unit const degree = GeoDataCoordinates::Degree;
    append( &url, "from", QString::number( route->source().latitude( degree ), 'f', 6 ) + "," + QString::number( route->source().longitude( degree ), 'f', 6 ) );
    for ( int i=1; i<route->size(); ++i ) {
        append( &url, "to", QString::number( route->at( i ).latitude( degree ), 'f', 6 ) + "," + QString::number( route->at( i ).longitude( degree ), 'f', 6 ) );
    }

    QString const unit = MarbleGlobal::getInstance()->locale()->measurementSystem() == QLocale::MetricSystem ? "k" : "m";
    append( &url, "units", unit );

    if ( settings["noMotorways"].toInt() ) {
        append( &url, "avoids", "Limited Access" );
    }
    if ( settings["noTollroads"].toInt() ) {
        append( &url, "avoids", "Toll road" );
    }
    if ( settings["noFerries"].toInt() ) {
        append( &url, "avoids", "Ferry" );
    }

    if ( !settings["preference"].toString().isEmpty() ) {
        append( &url, "routeType", settings["preference"].toString() );
    }

    QNetworkReply *reply = m_networkAccessManager->get( QNetworkRequest( QUrl( url ) ) );
    connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ),
             this, SLOT( handleError( QNetworkReply::NetworkError ) ) );

    QEventLoop eventLoop;

    connect( this, SIGNAL( routeCalculated( GeoDataDocument* ) ),
             &eventLoop, SLOT( quit() ) );

    eventLoop.exec();
}

void MapQuestRunner::retrieveData( QNetworkReply *reply )
{
    if ( reply->isFinished() ) {
        QByteArray data = reply->readAll();
        reply->deleteLater();
        //mDebug() << "Download completed: " << data;
        GeoDataDocument* document = parse( data );

        if ( !document ) {
            mDebug() << "Failed to parse the downloaded route data" << data;
        }

        emit routeCalculated( document );
    }
}

void MapQuestRunner::handleError( QNetworkReply::NetworkError error )
{
    mDebug() << " Error when retrieving mapquest.org route: " << error;
}

void MapQuestRunner::append(QString *input, const QString &key, const QString &value)
{
    *input += "&" + key + "=" + value;
}

int MapQuestRunner::maneuverType( int mapQuestId ) const
{
    /** @todo FIXME: review 10, 11 */
    switch( mapQuestId ) {
    case 0: return Maneuver::Straight ; // straight
    case 1: return Maneuver::SlightRight ; // slight right
    case 2: return Maneuver::Right ; // right
    case 3: return Maneuver::SharpRight ; // sharp right
    case 4: return Maneuver::TurnAround ; // reverse
    case 5: return Maneuver::SharpLeft ; // sharp left
    case 6: return Maneuver::Left ; // left
    case 7: return Maneuver::SlightLeft ; // slight left
    case 8: return Maneuver::TurnAround ; // right u-turn
    case 9: return Maneuver::TurnAround ; // left u-turn
    case 10: return Maneuver::Merge ; // right merge
    case 11: return Maneuver::Merge ; // left merge
    case 12: return Maneuver::Merge ; // right on ramp
    case 13: return Maneuver::Merge ; // left on ramp
    case 14: return Maneuver::ExitRight ; // right off ramp
    case 15: return Maneuver::ExitLeft ; // left off ramp
    case 16: return Maneuver::Right ; // right fork
    case 17: return Maneuver::Left ; // left fork
    case 18: return Maneuver::Continue ; // straight fork
    }

    return Maneuver::Unknown;
}

GeoDataDocument* MapQuestRunner::parse( const QByteArray &content ) const
{
    QDomDocument xml;
    if ( !xml.setContent( content ) ) {
        mDebug() << "Cannot parse xml file with routing instructions.";
        return 0;
    }

    // mDebug() << xml.toString(2);
    QDomElement root = xml.documentElement();

    GeoDataDocument* result = new GeoDataDocument();
    result->setName( "MapQuest" );
    GeoDataPlacemark* routePlacemark = new GeoDataPlacemark;
    routePlacemark->setName( "Route" );

    GeoDataLineString* routeWaypoints = new GeoDataLineString;
    QDomNodeList shapePoints = root.elementsByTagName( "shapePoints" );
    if ( shapePoints.size() == 1 ) {
        QDomNodeList geometry = shapePoints.at( 0 ).toElement().elementsByTagName( "latLng" );
        for ( int i=0; i<geometry.size(); ++i ) {
            double const lat = geometry.item( i ).namedItem( "lat" ).toElement().text().toDouble();
            double const lon = geometry.item( i ).namedItem( "lng" ).toElement().text().toDouble();
            GeoDataCoordinates const position( lon, lat, 0.0, GeoDataCoordinates::Degree );
            routeWaypoints->append( position );
        }
    }
    routePlacemark->setGeometry( routeWaypoints );

    QString name = "%1 %2 (MapQuest)";
    QString unit = "m";
    qreal length = routeWaypoints->length( EARTH_RADIUS );
    if (length >= 1000) {
        length /= 1000.0;
        unit = "km";
    }
    result->setName( name.arg( length, 0, 'f', 1 ).arg( unit ) );
    result->append( routePlacemark );

    QMap<int,int> mapping;
    QDomNodeList maneuvers = root.elementsByTagName( "maneuverIndexes" );
    if ( maneuvers.size() == 1 ) {
        maneuvers = maneuvers.at( 0 ).childNodes();
        for ( int i=0; i<maneuvers.size(); ++i ) {
            mapping[i] = maneuvers.at( i ).toElement().text().toInt();
            if ( mapping[i] == routeWaypoints->size() ) {
                --mapping[i];
            }
        }
    }

    QDomNodeList instructions = root.elementsByTagName( "maneuver" );
    unsigned int const lastInstruction = qMax<int>( 0, instructions.length()-1 ); // ignore the last 'Welcome to xy' instruction
    for ( unsigned int i = 0; i < lastInstruction; ++i ) {
        QDomElement node = instructions.item( i ).toElement();

        QDomNodeList maneuver = node.elementsByTagName( "turnType" );
        QDomNodeList textNodes = node.elementsByTagName( "narrative" );
        QDomNodeList points = node.elementsByTagName( "startPoint" );
        QDomNodeList streets = node.elementsByTagName( "streets" );

        Q_ASSERT( mapping.contains( i ) );
        if ( textNodes.size() == 1 && maneuver.size() == 1 && points.size() == 1 && mapping.contains( i ) ) {
            GeoDataPlacemark* instruction = new GeoDataPlacemark;
            instruction->setName( textNodes.at( 0 ).toElement().text() );

            GeoDataExtendedData extendedData;
            GeoDataData turnType;
            turnType.setName( "turnType" );
            turnType.setValue( maneuverType( maneuver.at( 0 ).toElement().text().toInt() ) );
            extendedData.addValue( turnType );
            if ( streets.size() == 1 ) {
                GeoDataData roadName;
                roadName.setName( "roadName" );
                roadName.setValue( streets.at( 0 ).toElement().text() );
                extendedData.addValue( roadName );
            }
            instruction->setExtendedData( extendedData );

            int const start = mapping[i];
            int const end = mapping.contains(i+1) ? mapping[i+1] : routeWaypoints->size()-1;
            if ( start >= 0 && start < routeWaypoints->size() && end < routeWaypoints->size() ) {
                instruction->setName( textNodes.item( 0 ).toElement().text() );
                GeoDataLineString *lineString = new GeoDataLineString;
                for ( int j=start; j<=end; ++j ) {
                    *lineString << GeoDataCoordinates( routeWaypoints->at( j ).longitude(), routeWaypoints->at( j ).latitude() );
                }

                if ( !lineString->isEmpty() ) {
                    instruction->setGeometry( lineString );
                    result->append( instruction );
                }
            }
        }
    }

    if ( routeWaypoints->size() < 1 ) {
        delete result;
        result = 0;
    }

    return result;
}

} // namespace Marble

#include "MapQuestRunner.moc"
<|endoftext|>


<commit_before>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#include "audio.hpp"
#include <cstdio>
#include <al.h>

AudioSystem::AudioSystem(bool create)
{
	if (create == true)
		CreateSystem();
}

AudioSystem::~AudioSystem()
{
	DestroySystem();
}

void AudioSystem::CreateSystem()
{
	m_Device = alcOpenDevice(nullptr);
	m_Context = alcCreateContext(m_Device, nullptr);
	alcMakeContextCurrent(m_Context);

	int error = alcGetError(m_Device);
	if (error != ALC_NO_ERROR) {
		printf("OpenAL error: %d\n", error);
		alcDestroyContext(m_Context);
		alcCloseDevice(m_Device);
		m_Context = nullptr;
		m_Device = nullptr;
	}
	alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
	alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);
}

void AudioSystem::DestroySystem()
{
	if (m_Context != nullptr)
		alcDestroyContext(m_Context);
	if (m_Device != nullptr)
		alcCloseDevice(m_Device);

	alcMakeContextCurrent(nullptr);

	m_Context = nullptr;
	m_Device = nullptr;
}

const ALCdevice *AudioSystem::GetDevice() const
{
	return m_Device;
}
<commit_msg>libTidyEngine: close audio device<commit_after>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#include "audio.hpp"
#include <cstdio>
#include <al.h>

AudioSystem::AudioSystem(bool create)
{
	if (create == true)
		CreateSystem();
}

AudioSystem::~AudioSystem()
{
	DestroySystem();
}

void AudioSystem::CreateSystem()
{
	m_Device = alcOpenDevice(nullptr);
	m_Context = alcCreateContext(m_Device, nullptr);
	alcMakeContextCurrent(m_Context);

	int error = alcGetError(m_Device);
	if (error != ALC_NO_ERROR) {
		printf("Error: OpenAL %d\n", error);
		alcDestroyContext(m_Context);
		alcCloseDevice(m_Device);
		m_Context = nullptr;
		m_Device = nullptr;
	}
	alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
	alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);
}

void AudioSystem::DestroySystem()
{
	alcDestroyContext(m_Context);
	alcCloseDevice(m_Device);

	m_Context = nullptr;
	m_Device = nullptr;
}

const ALCdevice *AudioSystem::GetDevice() const
{
	return m_Device;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "BlobRegistryImpl.h"

#include "BlobResourceHandle.h"
#include "ResourceError.h"
#include "ResourceHandle.h"
#include "ResourceLoader.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include <wtf/MainThread.h>
#include <wtf/StdLibExtras.h>

namespace WebCore {

#if !PLATFORM(CHROMIUM)
BlobRegistry& blobRegistry()
{
    ASSERT(isMainThread());
    DEFINE_STATIC_LOCAL(BlobRegistryImpl, instance, ());
    return instance;
}
#endif

bool BlobRegistryImpl::shouldLoadResource(const ResourceRequest& request) const
{
    // If the resource is not fetched using the GET method, bail out.
    if (!equalIgnoringCase(request.httpMethod(), "GET"))
        return false;

    return true;
}

PassRefPtr<ResourceHandle> BlobRegistryImpl::createResourceHandle(const ResourceRequest& request, ResourceHandleClient* client)
{
    if (!shouldLoadResource(request))
        return 0;

    return BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
}

bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
    if (!shouldLoadResource(request))
        return false;

    BlobResourceHandle::loadResourceSynchronously(m_blobs.get(request.url().string()), request, error, response, data);
    return true;
}

void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobDataItemList& items)
{
    for (BlobDataItemList::const_iterator iter = items.begin(); iter != items.end(); ++iter) {
        if (iter->type == BlobDataItem::Data)
            blobStorageData->m_data.appendData(iter->data, iter->offset, iter->length);
        else {
            ASSERT(iter->type == BlobDataItem::File);
            blobStorageData->m_data.appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
        }
    }
}

void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobDataItemList& items, long long offset, long long length)
{
    ASSERT(length != BlobDataItem::toEndOfFile);

    BlobDataItemList::const_iterator iter = items.begin();
    if (offset) {
        for (; iter != items.end(); ++iter) {
            if (offset >= iter->length)
                offset -= iter->length;
            else
                break;
        }
    }

    for (; iter != items.end() && length > 0; ++iter) {
        long long currentLength = iter->length - offset;
        long long newLength = currentLength > length ? length : currentLength;
        if (iter->type == BlobDataItem::Data)
            blobStorageData->m_data.appendData(iter->data, iter->offset + offset, newLength);
        else {
            ASSERT(iter->type == BlobDataItem::File);
            blobStorageData->m_data.appendFile(iter->path, iter->offset + offset, newLength, iter->expectedModificationTime);
        }
        length -= newLength;
        offset = 0;
    }
}

void BlobRegistryImpl::registerBlobURL(const KURL& url, PassOwnPtr<BlobData> blobData)
{
    ASSERT(isMainThread());

    RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create(blobData->contentType(), blobData->contentDisposition());

    // The blob data is stored in the "canonical" way. That is, it only contains a list of Data and File items.
    // 1) The Data item is denoted by the raw data and the range.
    // 2) The File item is denoted by the file path, the range and the expected modification time.
    // All the Blob items in the passing blob data are resolved and expanded into a set of Data and File items.

    for (BlobDataItemList::const_iterator iter = blobData->items().begin(); iter != blobData->items().end(); ++iter) {
        switch (iter->type) {
        case BlobDataItem::Data:
            blobStorageData->m_data.appendData(iter->data, 0, iter->data.length());
            break;
        case BlobDataItem::File:
            blobStorageData->m_data.appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
            break;
        case BlobDataItem::Blob:
            if (m_blobs.contains(iter->url.string()))
                appendStorageItems(blobStorageData.get(), m_blobs.get(iter->url.string())->items(), iter->offset, iter->length);
            break;
        }
    }

    m_blobs.set(url.string(), blobStorageData);
}

void BlobRegistryImpl::registerBlobURL(const KURL& url, const KURL& srcURL)
{
    ASSERT(isMainThread());

    RefPtr<BlobStorageData> src = m_blobs.get(srcURL.string());
    ASSERT(src);
    if (!src)
        return;

    RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create(src->contentType(), src->contentDisposition());
    appendStorageItems(blobStorageData.get(), src->items());

    m_blobs.set(url.string(), blobStorageData);
}

void BlobRegistryImpl::unregisterBlobURL(const KURL& url)
{
    ASSERT(isMainThread());
    m_blobs.remove(url.string());
}

PassRefPtr<BlobStorageData> BlobRegistryImpl::getBlobDataFromURL(const KURL& url) const
{
    ASSERT(isMainThread());
    return m_blobs.get(url.string());
}

} // namespace WebCore
<commit_msg>2010-08-30  Jian Li  <jianli@chromium.org><commit_after>/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if ENABLE(BLOB)

#include "BlobRegistryImpl.h"

#include "BlobResourceHandle.h"
#include "ResourceError.h"
#include "ResourceHandle.h"
#include "ResourceLoader.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include <wtf/MainThread.h>
#include <wtf/StdLibExtras.h>

namespace WebCore {

#if !PLATFORM(CHROMIUM)
BlobRegistry& blobRegistry()
{
    ASSERT(isMainThread());
    DEFINE_STATIC_LOCAL(BlobRegistryImpl, instance, ());
    return instance;
}
#endif

bool BlobRegistryImpl::shouldLoadResource(const ResourceRequest& request) const
{
    // If the resource is not fetched using the GET method, bail out.
    if (!equalIgnoringCase(request.httpMethod(), "GET"))
        return false;

    return true;
}

PassRefPtr<ResourceHandle> BlobRegistryImpl::createResourceHandle(const ResourceRequest& request, ResourceHandleClient* client)
{
    if (!shouldLoadResource(request))
        return 0;

    return BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
}

bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
    if (!shouldLoadResource(request))
        return false;

    BlobResourceHandle::loadResourceSynchronously(m_blobs.get(request.url().string()), request, error, response, data);
    return true;
}

void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobDataItemList& items)
{
    for (BlobDataItemList::const_iterator iter = items.begin(); iter != items.end(); ++iter) {
        if (iter->type == BlobDataItem::Data)
            blobStorageData->m_data.appendData(iter->data, iter->offset, iter->length);
        else {
            ASSERT(iter->type == BlobDataItem::File);
            blobStorageData->m_data.appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
        }
    }
}

void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, const BlobDataItemList& items, long long offset, long long length)
{
    ASSERT(length != BlobDataItem::toEndOfFile);

    BlobDataItemList::const_iterator iter = items.begin();
    if (offset) {
        for (; iter != items.end(); ++iter) {
            if (offset >= iter->length)
                offset -= iter->length;
            else
                break;
        }
    }

    for (; iter != items.end() && length > 0; ++iter) {
        long long currentLength = iter->length - offset;
        long long newLength = currentLength > length ? length : currentLength;
        if (iter->type == BlobDataItem::Data)
            blobStorageData->m_data.appendData(iter->data, iter->offset + offset, newLength);
        else {
            ASSERT(iter->type == BlobDataItem::File);
            blobStorageData->m_data.appendFile(iter->path, iter->offset + offset, newLength, iter->expectedModificationTime);
        }
        length -= newLength;
        offset = 0;
    }
}

void BlobRegistryImpl::registerBlobURL(const KURL& url, PassOwnPtr<BlobData> blobData)
{
    ASSERT(isMainThread());

    RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create(blobData->contentType(), blobData->contentDisposition());

    // The blob data is stored in the "canonical" way. That is, it only contains a list of Data and File items.
    // 1) The Data item is denoted by the raw data and the range.
    // 2) The File item is denoted by the file path, the range and the expected modification time.
    // All the Blob items in the passing blob data are resolved and expanded into a set of Data and File items.

    for (BlobDataItemList::const_iterator iter = blobData->items().begin(); iter != blobData->items().end(); ++iter) {
        switch (iter->type) {
        case BlobDataItem::Data:
            blobStorageData->m_data.appendData(iter->data, 0, iter->data.length());
            break;
        case BlobDataItem::File:
            blobStorageData->m_data.appendFile(iter->path, iter->offset, iter->length, iter->expectedModificationTime);
            break;
        case BlobDataItem::Blob:
            if (m_blobs.contains(iter->url.string()))
                appendStorageItems(blobStorageData.get(), m_blobs.get(iter->url.string())->items(), iter->offset, iter->length);
            break;
        }
    }

    m_blobs.set(url.string(), blobStorageData);
}

void BlobRegistryImpl::registerBlobURL(const KURL& url, const KURL& srcURL)
{
    ASSERT(isMainThread());

    RefPtr<BlobStorageData> src = m_blobs.get(srcURL.string());
    ASSERT(src);
    if (!src)
        return;

    RefPtr<BlobStorageData> blobStorageData = BlobStorageData::create(src->contentType(), src->contentDisposition());
    appendStorageItems(blobStorageData.get(), src->items());

    m_blobs.set(url.string(), blobStorageData);
}

void BlobRegistryImpl::unregisterBlobURL(const KURL& url)
{
    ASSERT(isMainThread());
    m_blobs.remove(url.string());
}

PassRefPtr<BlobStorageData> BlobRegistryImpl::getBlobDataFromURL(const KURL& url) const
{
    ASSERT(isMainThread());
    return m_blobs.get(url.string());
}

} // namespace WebCore

#endif // ENABLE(BLOB)
<|endoftext|>


<commit_before>#include "minimal_scene.h"

#include "augs/templates/algorithm_templates.h"

#include "game/enums/party_category.h"

#include "test_scenes/test_scene_flavours.h"
#include "test_scenes/ingredients/ingredients.h"
#include "test_scenes/test_scenes_content.h"

#include "game/transcendental/cosmos.h"
#include "game/organization/all_component_includes.h"
#include "game/organization/all_messages_includes.h"
#include "game/transcendental/logic_step.h"

#include "game/detail/inventory/perform_transfer.h"
#include "view/viewables/image_cache.h"

namespace test_scenes {
	entity_id minimal_scene::populate(const loaded_image_caches_map&, const logic_step step) const {
		const int num_characters = 1;

		std::vector<entity_id> new_characters;
		new_characters.resize(num_characters);

		for (int i = 0; i < num_characters; ++i) {
			transformr transform;

			if (i == 0) {
			}
			else if (i == 1) {
				transform.pos.x += 200;
			}

			const auto new_character = prefabs::create_metropolis_soldier(step, transform, typesafe_sprintf("player%x", i));

			new_characters[i] = new_character;

			if (i == 0) {
				new_character.get<components::sentience>().get<health_meter_instance>().set_value(100);
				new_character.get<components::sentience>().get<health_meter_instance>().set_maximum_value(100);
				new_character.get<components::attitude>().parties = party_category::RESISTANCE_CITIZEN;
				new_character.get<components::attitude>().hostile_parties = party_category::METROPOLIS_CITIZEN;
			}
			else if (i == 1) {
				new_character.get<components::sentience>().get<health_meter_instance>().set_value(100);
				new_character.get<components::sentience>().get<health_meter_instance>().set_maximum_value(100);
				new_character.get<components::attitude>().parties = party_category::METROPOLIS_CITIZEN;
				new_character.get<components::attitude>().hostile_parties = party_category::RESISTANCE_CITIZEN;
			}

			auto& sentience = new_character.get<components::sentience>();

			fill_range(sentience.learned_spells, true);
		}

		prefabs::create_sample_rifle(step, vec2(100, -500 + 50),
			prefabs::create_sample_magazine(step, vec2(100, -650),
				prefabs::create_cyan_charge(step, vec2(0, 0))));

		prefabs::create_force_grenade(step, { 100, 100 });
		prefabs::create_force_grenade(step, { 200, 100 });
		prefabs::create_force_grenade(step, { 300, 100});

		/* Test: create cyan charges first, only then magazine, and reinfer. */
		const auto charge = prefabs::create_cyan_charge(step, vec2(0, 0));
		prefabs::create_sample_magazine(step, vec2(100, -650), charge);

		cosmic::reinfer_all_entities(step.get_cosmos());

		// _controlfp(0, _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID | _EM_DENORMAL);
		return new_characters[0];
	}
}
<commit_msg>added aligner to minimal test scene<commit_after>#include "minimal_scene.h"

#include "augs/templates/algorithm_templates.h"

#include "game/enums/party_category.h"

#include "test_scenes/test_scene_flavours.h"
#include "test_scenes/ingredients/ingredients.h"
#include "test_scenes/test_scenes_content.h"

#include "game/transcendental/cosmos.h"
#include "game/organization/all_component_includes.h"
#include "game/organization/all_messages_includes.h"
#include "game/transcendental/logic_step.h"

#include "game/detail/inventory/perform_transfer.h"
#include "view/viewables/image_cache.h"

#include "test_scenes/scenes/test_scene_node.h"
#include "augs/math/cascade_aligner.h"

namespace test_scenes {
	entity_id minimal_scene::populate(const loaded_image_caches_map& caches, const logic_step step) const {
		auto& world = step.get_cosmos();

#if 0
		auto create = [&](auto&&... args) {
			return create_test_scene_entity(world, std::forward<decltype(args)>(args)...);
		};
#endif

		auto get_size_of = [&caches](const auto id) {
			return vec2i(caches.at(to_image_id(id)).get_original_size());
		};

		const int num_characters = 1;

		std::vector<entity_id> new_characters;
		new_characters.resize(num_characters);

		for (int i = 0; i < num_characters; ++i) {
			transformr transform;

			if (i == 0) {
			}
			else if (i == 1) {
				transform.pos.x += 200;
			}

			const auto new_character = prefabs::create_metropolis_soldier(step, transform, typesafe_sprintf("player%x", i));

			new_characters[i] = new_character;

			if (i == 0) {
				new_character.get<components::sentience>().get<health_meter_instance>().set_value(100);
				new_character.get<components::sentience>().get<health_meter_instance>().set_maximum_value(100);
				new_character.get<components::attitude>().parties = party_category::RESISTANCE_CITIZEN;
				new_character.get<components::attitude>().hostile_parties = party_category::METROPOLIS_CITIZEN;
			}
			else if (i == 1) {
				new_character.get<components::sentience>().get<health_meter_instance>().set_value(100);
				new_character.get<components::sentience>().get<health_meter_instance>().set_maximum_value(100);
				new_character.get<components::attitude>().parties = party_category::METROPOLIS_CITIZEN;
				new_character.get<components::attitude>().hostile_parties = party_category::RESISTANCE_CITIZEN;
			}

			auto& sentience = new_character.get<components::sentience>();

			fill_range(sentience.learned_spells, true);
		}

#if 0
		prefabs::create_sample_rifle(step, vec2(100, -500 + 50),
			prefabs::create_sample_magazine(step, vec2(100, -650),
				prefabs::create_cyan_charge(step, vec2(0, 0))));

		prefabs::create_force_grenade(step, { 100, 100 });
		prefabs::create_force_grenade(step, { 200, 100 });
		prefabs::create_force_grenade(step, { 300, 100});

		/* Test: create cyan charges first, only then magazine, and reinfer. */
		const auto charge = prefabs::create_cyan_charge(step, vec2(0, 0));
		prefabs::create_sample_magazine(step, vec2(100, -650), charge);
#endif

		{
			const vec2 floor_size = get_size_of(test_scene_image_id::FLOOR);
			const auto total_floor_size = floor_size * 10;
			const auto floor_origin = vec2(512, -768);

			auto floor_align = [&](const auto flavour_id) {
				return make_cascade_aligner(
					floor_origin,
					total_floor_size,
					test_scene_node { world, flavour_id }
				);
			};

			floor_align(test_sprite_decorations::FLOOR).set_size(total_floor_size);
		}

		cosmic::reinfer_all_entities(world);

		// _controlfp(0, _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID | _EM_DENORMAL);
		return new_characters[0];
	}
}
<|endoftext|>


<commit_before>#include "libs/array/sort.h"
#include "object/array.h"
#include "object/argument.h"
#include "object/function.h"

#include <algorithm>

namespace grok {
namespace libs {
using namespace grok::vm;
using namespace grok::obj;

bool MyPred(std::shared_ptr<Object> A, std::shared_ptr<Object> B)
{
    auto strA = A->as<JSObject>()->ToString();
    auto strB = B->as<JSObject>()->ToString();

    return strA < strB;
}

void SortArrayWithDefaultPredicate(std::shared_ptr<JSArray> arr)
{
    std::sort(arr->begin(), arr->end(), MyPred);
}

void SortStringWithDefaultPredicate(std::shared_ptr<JSString> str)
{
    auto &S = str->GetString();
    std::sort(S.begin(), S.end());
}

void SortWithDefaultPredicate(std::shared_ptr<Object> A)
{
    if (IsJSArray(A)) {
        SortArrayWithDefaultPredicate(A->as<JSArray>());
    } else if (IsJSString(A)) {
        SortStringWithDefaultPredicate(A->as<JSString>());
    } else {
        return;
    }
}

void SortWithPredicate(std::shared_ptr<Object> obj,
        std::shared_ptr<Function> func)
{
    if (!IsJSArray(obj))
        return;

    auto A = obj->as<JSArray>();
    std::sort(A->begin(), A->end(),
            [&func](auto a, auto b) {
                auto Args = CreateArgumentObject()->as<Argument>();
                Args->Push(a);
                Args->Push(b);
                auto vm = GetGlobalVMContext()->GetVM();

                auto R = CallJSFunction(func, Args, vm);

                int n = 0;
                if (IsJSNumber(R)) {
                    n = (int)R->as<JSNumber>()->GetNumber();
                    return n < 0 ? true : false;
                }
                return false;
            });
}

void SortInternal(std::shared_ptr<Object> A,
    std::shared_ptr<Object> pred, bool use_default_pred)
{
    if (use_default_pred) {
        SortWithDefaultPredicate(A);
    } else {
        if (!IsFunction(pred))
            SortWithDefaultPredicate(A);
        else
            SortWithPredicate(A, pred->as<Function>());
    }
}

// this is a very generic sort function and can be applied to strings
// and arrays or any other object having property length
std::shared_ptr<Object> ArraySort(std::shared_ptr<Argument> Args)
{
    bool use_default_pred = false;

    // object on which we are applying sort
    auto Obj = Args->GetProperty("this");
    auto O = Obj->as<JSObject>();

    // predicate
    auto Pred = Args->GetProperty("pred");

    if (IsUndefined(Pred)) {
        use_default_pred = true;
    }

    SortInternal(Obj, Pred, use_default_pred);
    return Obj;
}

}
} // grok
<commit_msg>Fix: Use JSDouble over JSNumber<commit_after>#include "libs/array/sort.h"
#include "object/array.h"
#include "object/argument.h"
#include "object/function.h"

#include <algorithm>

namespace grok {
namespace libs {
using namespace grok::vm;
using namespace grok::obj;

bool MyPred(std::shared_ptr<Object> A, std::shared_ptr<Object> B)
{
    auto strA = A->as<JSObject>()->ToString();
    auto strB = B->as<JSObject>()->ToString();

    return strA < strB;
}

void SortArrayWithDefaultPredicate(std::shared_ptr<JSArray> arr)
{
    std::sort(arr->begin(), arr->end(), MyPred);
}

void SortStringWithDefaultPredicate(std::shared_ptr<JSString> str)
{
    auto &S = str->GetString();
    std::sort(S.begin(), S.end());
}

void SortWithDefaultPredicate(std::shared_ptr<Object> A)
{
    if (IsJSArray(A)) {
        SortArrayWithDefaultPredicate(A->as<JSArray>());
    } else if (IsJSString(A)) {
        SortStringWithDefaultPredicate(A->as<JSString>());
    } else {
        return;
    }
}

void SortWithPredicate(std::shared_ptr<Object> obj,
        std::shared_ptr<Function> func)
{
    if (!IsJSArray(obj))
        return;

    auto A = obj->as<JSArray>();
    std::sort(A->begin(), A->end(),
            [&func](auto a, auto b) {
                auto Args = CreateArgumentObject()->as<Argument>();
                Args->Push(a);
                Args->Push(b);
                auto vm = GetGlobalVMContext()->GetVM();

                auto R = CallJSFunction(func, Args, vm);

                int n = 0;
                if (IsJSNumber(R)) {
                    n = (int)R->as<JSDouble>()->GetNumber();
                    return n < 0 ? true : false;
                }
                return false;
            });
}

void SortInternal(std::shared_ptr<Object> A,
    std::shared_ptr<Object> pred, bool use_default_pred)
{
    if (use_default_pred) {
        SortWithDefaultPredicate(A);
    } else {
        if (!IsFunction(pred))
            SortWithDefaultPredicate(A);
        else
            SortWithPredicate(A, pred->as<Function>());
    }
}

// this is a very generic sort function and can be applied to strings
// and arrays or any other object having property length
std::shared_ptr<Object> ArraySort(std::shared_ptr<Argument> Args)
{
    bool use_default_pred = false;

    // object on which we are applying sort
    auto Obj = Args->GetProperty("this");
    auto O = Obj->as<JSObject>();

    // predicate
    auto Pred = Args->GetProperty("pred");

    if (IsUndefined(Pred)) {
        use_default_pred = true;
    }

    SortInternal(Obj, Pred, use_default_pred);
    return Obj;
}

}
} // grok
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/core/ObjectFactory.h>
#include <sofa/component/loader/MeshOffLoader.h>
#include <sofa/helper/system/SetDirectory.h>

namespace sofa
{

namespace component
{

namespace loader
{

using namespace sofa::defaulttype;

SOFA_DECL_CLASS(MeshOffLoader)

int MeshOffLoaderClass = core::RegisterObject("Specific mesh loader for Off file format.")
        .add< MeshOffLoader >()
        ;

bool MeshOffLoader::load()
{
    sout << "Loading OFF file: " << m_filename << sendl;

    bool fileRead = false;

    // -- Loading file
    const char* filename = m_filename.getFullPath().c_str();
    std::string cmd;
    std::ifstream file(filename);

    if (!file.good())
    {
        serr << "Error: MeshOffLoader: Cannot read file '" << m_filename << "'." << sendl;
        return false;
    }

    file >> cmd;
    if (cmd != "OFF")
    {
        serr << "Error: MeshOffLoader: Not a OFF file (header problem) '" << m_filename << "'." << sendl;
        return false;
    }

    // -- Reading file
    fileRead = this->readOFF (file,filename);
    file.close();

    return fileRead;
}

bool MeshOffLoader::readOFF (std::ifstream &file, const char* /* filename */ )
{
    sout << "MeshOffLoader::readOFF" << sendl;

    helper::vector<sofa::defaulttype::Vector3>& my_positions = *(positions.beginEdit());

    helper::vector<helper::fixed_array <unsigned int,3> >& my_triangles = *(triangles.beginEdit());
    helper::vector<helper::fixed_array <unsigned int,4> >& my_quads = *(quads.beginEdit());

    unsigned int numberOfVertices, numberOfFaces, numberOfEdges;
    unsigned int currentNumberOfVertices, currentNumberOfFaces;
    Vec3d vertex;
    helper::fixed_array <unsigned int,3> triangle;
    helper::fixed_array <unsigned int,4> quad;
    std::string line;

    while( !file.eof() && (numberOfVertices == 0) )
    {
        std::getline(file,line);

        if (line.empty()) continue;
        if (line[0] == '#') continue;

        std::istringstream values(line);
        values >> numberOfVertices >> numberOfFaces >> numberOfEdges;
    }
    currentNumberOfVertices = 0;

    //Vertices
    while( !file.eof() &&  currentNumberOfVertices < numberOfVertices)
    {
        std::getline(file,line);

        if (line.empty()) continue;
        if (line[0] == '#') continue;

        std::istringstream values(line);

        values >> vertex[0] >> vertex[1] >> vertex[2];
        my_positions.push_back(Vector3(vertex[0],vertex[1], vertex[2]));

        currentNumberOfVertices++;
    }
    currentNumberOfFaces = 0;
    //Faces
    while( !file.eof() && currentNumberOfFaces < numberOfFaces)
    {
        std::getline(file,line);
        if (line.empty()) continue;
        if (line[0] == '#') continue;

        std::istringstream values(line);
        unsigned int numberOfVerticesPerFace = 0;

        values >> numberOfVerticesPerFace;
        if (numberOfVerticesPerFace < 3 || numberOfVerticesPerFace > 4)
            continue;

        if (numberOfVerticesPerFace == 3)
        {
            values >> triangle[0] >> triangle[1] >> triangle[2];
            addTriangle(&my_triangles, triangle);
        }
        if (numberOfVerticesPerFace == 4)
        {
            values >> quad[0] >> quad[1] >> quad[2] >> quad[3];
            addQuad(&my_quads, quad);
        }
        currentNumberOfFaces++;
    }

    positions.endEdit();
    triangles.endEdit();
    quads.endEdit();

    return true;
}
} // namespace loader

} // namespace component

} // namespace sofa

<commit_msg>r5862/sofa-dev : FIX: MeshOffLoader<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/core/ObjectFactory.h>
#include <sofa/component/loader/MeshOffLoader.h>
#include <sofa/helper/system/SetDirectory.h>

namespace sofa
{

namespace component
{

namespace loader
{

using namespace sofa::defaulttype;

SOFA_DECL_CLASS(MeshOffLoader)

int MeshOffLoaderClass = core::RegisterObject("Specific mesh loader for Off file format.")
        .add< MeshOffLoader >()
        ;

bool MeshOffLoader::load()
{
    sout << "Loading OFF file: " << m_filename << sendl;

    bool fileRead = false;

    // -- Loading file
    const char* filename = m_filename.getFullPath().c_str();
    std::string cmd;
    std::ifstream file(filename);

    if (!file.good())
    {
        serr << "Error: MeshOffLoader: Cannot read file '" << m_filename << "'." << sendl;
        return false;
    }

    file >> cmd;
    if (cmd != "OFF")
    {
        serr << "Error: MeshOffLoader: Not a OFF file (header problem) '" << m_filename << "'." << sendl;
        return false;
    }

    // -- Reading file
    fileRead = this->readOFF (file,filename);
    file.close();

    return fileRead;
}

bool MeshOffLoader::readOFF (std::ifstream &file, const char* /* filename */ )
{
    sout << "MeshOffLoader::readOFF" << sendl;

    helper::vector<sofa::defaulttype::Vector3>& my_positions = *(positions.beginEdit());

    helper::vector<helper::fixed_array <unsigned int,3> >& my_triangles = *(triangles.beginEdit());
    helper::vector<helper::fixed_array <unsigned int,4> >& my_quads = *(quads.beginEdit());

    unsigned int numberOfVertices = 0, numberOfFaces = 0, numberOfEdges = 0;
    unsigned int currentNumberOfVertices = 0, currentNumberOfFaces = 0;
    Vec3d vertex;
    helper::fixed_array <unsigned int,3> triangle;
    helper::fixed_array <unsigned int,4> quad;
    std::string line;

    while( !file.eof() && (numberOfVertices == 0) )
    {
        std::getline(file,line);

        if (line.empty()) continue;
        if (line[0] == '#') continue;

        std::istringstream values(line);
        values >> numberOfVertices >> numberOfFaces >> numberOfEdges;
    }
    sout << "vertices = "<< numberOfVertices << sendl;
    sout << "faces = "<< numberOfFaces << sendl;
    sout << "edges = "<< numberOfEdges << sendl;

    currentNumberOfVertices = 0;

    //Vertices
    while( !file.eof() &&  currentNumberOfVertices < numberOfVertices)
    {
        std::getline(file,line);

        if (line.empty()) continue;
        if (line[0] == '#') continue;

        std::istringstream values(line);

        values >> vertex[0] >> vertex[1] >> vertex[2];
        my_positions.push_back(Vector3(vertex[0],vertex[1], vertex[2]));

        currentNumberOfVertices++;
    }
    currentNumberOfFaces = 0;
    //Faces
    while( !file.eof() && currentNumberOfFaces < numberOfFaces)
    {
        std::getline(file,line);
        if (line.empty()) continue;
        if (line[0] == '#') continue;

        std::istringstream values(line);
        unsigned int numberOfVerticesPerFace = 0;

        values >> numberOfVerticesPerFace;
        if (numberOfVerticesPerFace < 3 || numberOfVerticesPerFace > 4)
            continue;

        if (numberOfVerticesPerFace == 3)
        {
            values >> triangle[0] >> triangle[1] >> triangle[2];
            addTriangle(&my_triangles, triangle);
        }
        if (numberOfVerticesPerFace == 4)
        {
            values >> quad[0] >> quad[1] >> quad[2] >> quad[3];
            addQuad(&my_quads, quad);
        }
        currentNumberOfFaces++;
    }

    positions.endEdit();
    triangles.endEdit();
    quads.endEdit();

    return true;
}
} // namespace loader

} // namespace component

} // namespace sofa

<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CommonIO.cpp
 * @author Gav Wood
 * @date 2014
 */

#include "CommonIO.h"

#include <fstream>
#include "Exceptions.h"
using namespace std;
using namespace dev;

string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
{
	stringstream ret;
	if (_html)
		ret << "
";
	for (unsigned i = 0; i < _bytes.size(); i += _width)
	{
		ret << hex << setw(4) << setfill('0') << i << " ";
		for (unsigned j = i; j < i + _width; ++j)
			if (j < _bytes.size())
				if (_bytes[j] >= 32 && _bytes[j] < 127)
					if ((char)_bytes[j] == '<' && _html)
						ret << "<";
					else if ((char)_bytes[j] == '&' && _html)
						ret << "&";
					else
						ret << (char)_bytes[j];
				else
					ret << '?';
			else
				ret << ' ';
		ret << " ";
		for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j)
			ret << setfill('0') << setw(2) << hex << (unsigned)_bytes[j] << " ";
		ret << "\n";
	}
	if (_html)
		ret << "
";
	return ret.str();
}

// Don't forget to delete[] later.
bytesRef dev::contentsNew(std::string const& _file)
{
	std::ifstream is(_file, std::ifstream::binary);
	if (!is)
		return bytesRef();
	// get length of file:
	is.seekg (0, is.end);
	streamoff length = is.tellg();
	if (length == 0) // return early, MSVC does not like reading 0 bytes
		return bytesRef();
	is.seekg (0, is.beg);
	bytesRef ret(new byte[length], length);
	is.read((char*)ret.data(), length);
	is.close();
	return ret;
}

bytes dev::contents(std::string const& _file)
{
	std::ifstream is(_file, std::ifstream::binary);
	if (!is)
		return bytes();
	// get length of file:
	is.seekg (0, is.end);
	streamoff length = is.tellg();
	if (length == 0) // return early, MSVC does not like reading 0 bytes
		return bytes();
	is.seekg (0, is.beg);
	bytes ret(length);
	is.read((char*)ret.data(), length);
	is.close();
	return ret;
}

string dev::contentsString(std::string const& _file)
{
	std::ifstream is(_file, std::ifstream::binary);
	if (!is)
		return string();
	// get length of file:
	is.seekg (0, is.end);
	streamoff length = is.tellg();
	if (length == 0) // return early, MSVC does not like reading 0 bytes
		return string();
	is.seekg (0, is.beg);
	string ret;
	ret.resize(length);
	is.read((char*)ret.data(), length);
	is.close();
	return ret;
}

void dev::writeFile(std::string const& _file, bytesConstRef _data)
{
	ofstream(_file, ios::trunc).write((char const*)_data.data(), _data.size());
}

<commit_msg>Win32/MSVC requires ios::binary flag on ofstream to correctly write dag file<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CommonIO.cpp
 * @author Gav Wood
 * @date 2014
 */

#include "CommonIO.h"

#include <fstream>
#include "Exceptions.h"
using namespace std;
using namespace dev;

string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
{
	stringstream ret;
	if (_html)
		ret << "
";
	for (unsigned i = 0; i < _bytes.size(); i += _width)
	{
		ret << hex << setw(4) << setfill('0') << i << " ";
		for (unsigned j = i; j < i + _width; ++j)
			if (j < _bytes.size())
				if (_bytes[j] >= 32 && _bytes[j] < 127)
					if ((char)_bytes[j] == '<' && _html)
						ret << "<";
					else if ((char)_bytes[j] == '&' && _html)
						ret << "&";
					else
						ret << (char)_bytes[j];
				else
					ret << '?';
			else
				ret << ' ';
		ret << " ";
		for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j)
			ret << setfill('0') << setw(2) << hex << (unsigned)_bytes[j] << " ";
		ret << "\n";
	}
	if (_html)
		ret << "
";
	return ret.str();
}

// Don't forget to delete[] later.
bytesRef dev::contentsNew(std::string const& _file)
{
	std::ifstream is(_file, std::ifstream::binary);
	if (!is)
		return bytesRef();
	// get length of file:
	is.seekg (0, is.end);
	streamoff length = is.tellg();
	if (length == 0) // return early, MSVC does not like reading 0 bytes
		return bytesRef();
	is.seekg (0, is.beg);
	bytesRef ret(new byte[length], length);
	is.read((char*)ret.data(), length);
	is.close();
	return ret;
}

bytes dev::contents(std::string const& _file)
{
	std::ifstream is(_file, std::ifstream::binary);
	if (!is)
		return bytes();
	// get length of file:
	is.seekg (0, is.end);
	streamoff length = is.tellg();
	if (length == 0) // return early, MSVC does not like reading 0 bytes
		return bytes();
	is.seekg (0, is.beg);
	bytes ret(length);
	is.read((char*)ret.data(), length);
	is.close();
	return ret;
}

string dev::contentsString(std::string const& _file)
{
	std::ifstream is(_file, std::ifstream::binary);
	if (!is)
		return string();
	// get length of file:
	is.seekg (0, is.end);
	streamoff length = is.tellg();
	if (length == 0) // return early, MSVC does not like reading 0 bytes
		return string();
	is.seekg (0, is.beg);
	string ret;
	ret.resize(length);
	is.read((char*)ret.data(), length);
	is.close();
	return ret;
}

void dev::writeFile(std::string const& _file, bytesConstRef _data)
{
	ofstream(_file, ios::trunc|ios::binary).write((char const*)_data.data(), _data.size());
}

<|endoftext|>