<commit_before>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  This program 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 2                   *
 *  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 General Public License for more details.                                     *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "daemon.h"
#include "serializer.h"
#include "generator.h"
#include "device.h"
#include "kscreenadaptor.h"
#include "debug.h"

#include <QTimer>
#include <QAction>
#include <QShortcut>
#include <QLoggingCategory>

#include <KLocalizedString>
#include <KActionCollection>
#include <KPluginFactory>
#include <KGlobalAccel>

#include <kscreen/config.h>
#include <kscreen/configmonitor.h>
#include <kscreen/getconfigoperation.h>
#include <kscreen/setconfigoperation.h>

K_PLUGIN_FACTORY(KScreenDaemonFactory, registerPlugin<KScreenDaemon>();)

KScreenDaemon::KScreenDaemon(QObject* parent, const QList< QVariant >& )
 : KDEDModule(parent)
 , m_monitoredConfig(0)
 , m_iteration(0)
 , m_monitoring(false)
 , m_changeCompressor(new QTimer())
 , m_buttonTimer(new QTimer())
 , m_saveTimer(new QTimer())

{
    QMetaObject::invokeMethod(this, "requestConfig", Qt::QueuedConnection);
}

void KScreenDaemon::requestConfig()
{
    connect(new KScreen::GetConfigOperation, &KScreen::GetConfigOperation::finished,
            this, &KScreenDaemon::configReady);
}

void KScreenDaemon::configReady(KScreen::ConfigOperation* op)
{
    if (op->hasError()) {
        return;
    }

    m_monitoredConfig = qobject_cast<KScreen::GetConfigOperation*>(op)->config();
    qCDebug(KSCREEN_KDED) << "Config" << m_monitoredConfig.data() << "is ready";
    KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);

    init();
}

KScreenDaemon::~KScreenDaemon()
{
    delete m_changeCompressor;
    delete m_saveTimer;
    delete m_buttonTimer;

    Generator::destroy();
    Device::destroy();
}

void KScreenDaemon::init()
{
    KActionCollection *coll = new KActionCollection(this);
    QAction* action = coll->addAction(QStringLiteral("display"));
    action->setText(i18n("Switch Display" ));
    KGlobalAccel::self()->setShortcut(action, QList<QKeySequence>() << QKeySequence(Qt::Key_Display));
    connect(action, &QAction::triggered, [&](bool) { displayButton(); });

    new KScreenAdaptor(this);

    m_buttonTimer->setInterval(300);
    m_buttonTimer->setSingleShot(true);
    connect(m_buttonTimer, &QTimer::timeout, this, &KScreenDaemon::applyGenericConfig);

    m_saveTimer->setInterval(300);
    m_saveTimer->setSingleShot(true);
    connect(m_saveTimer, &QTimer::timeout, this, &KScreenDaemon::saveCurrentConfig);

    m_changeCompressor->setInterval(10);
    m_changeCompressor->setSingleShot(true);
    connect(m_changeCompressor, &QTimer::timeout, this, &KScreenDaemon::applyConfig);

    connect(Device::self(), &Device::lidClosedChanged, this, &KScreenDaemon::lidClosedChanged);
    connect(Device::self(), &Device::resumingFromSuspend,
            [&]() {
                qCDebug(KSCREEN_KDED) << "Resumed from suspend, checking for screen changes";
                // We don't care about the result, we just want to force the backend
                // to query XRandR so that it will detect possible changes that happened
                // while the computer was suspended, and will emit the change events.
                new KScreen::GetConfigOperation(KScreen::GetConfigOperation::NoEDID, this);
            });

    connect(Generator::self(), &Generator::ready,
            this, &KScreenDaemon::applyConfig);

    Generator::self()->setCurrentConfig(m_monitoredConfig);
    monitorConnectedChange();
}

void KScreenDaemon::doApplyConfig(const KScreen::ConfigPtr& config)
{
    qCDebug(KSCREEN_KDED) << "doApplyConfig()";
    setMonitorForChanges(false);

    connect(new KScreen::SetConfigOperation(config), &KScreen::SetConfigOperation::finished,
            [&]() {
                qCDebug(KSCREEN_KDED) << "Config applied";
                setMonitorForChanges(true);
            });
}

void KScreenDaemon::applyConfig()
{
    qCDebug(KSCREEN_KDED) << "Applying config";
    if (Serializer::configExists(m_monitoredConfig)) {
        applyKnownConfig();
        return;
    }

    applyIdealConfig();
}

void KScreenDaemon::applyKnownConfig()
{
    const QString configId = Serializer::configId(m_monitoredConfig);
    qCDebug(KSCREEN_KDED) << "Applying known config" << configId;

    KScreen::ConfigPtr config = Serializer::config(m_monitoredConfig, configId);
    if (!KScreen::Config::canBeApplied(config)) {
        return applyIdealConfig();
    }

    doApplyConfig(config);
}

void KScreenDaemon::applyIdealConfig()
{
    qCDebug(KSCREEN_KDED) << "Applying ideal config";
    doApplyConfig(Generator::self()->idealConfig(m_monitoredConfig));
}

void KScreenDaemon::configChanged()
{
    qCDebug(KSCREEN_KDED) << "Change detected";
    // Reset timer, delay the writeback
    m_saveTimer->start();
}

void KScreenDaemon::saveCurrentConfig()
{
    qCDebug(KSCREEN_KDED) << "Saving current config to file";
    Serializer::saveConfig(m_monitoredConfig);
}

void KScreenDaemon::displayButton()
{
    qCDebug(KSCREEN_KDED) << "displayBtn triggered";
    if (m_buttonTimer->isActive()) {
        qCDebug(KSCREEN_KDED) << "Too fast, cowboy";
        return;
    }

    m_buttonTimer->start();
}

void KScreenDaemon::resetDisplaySwitch()
{
    qCDebug(KSCREEN_KDED) << "resetDisplaySwitch()";
    m_iteration = 0;
}

void KScreenDaemon::applyGenericConfig()
{
    if (m_iteration == 5) {
        m_iteration = 0;
    }

    m_iteration++;
    qCDebug(KSCREEN_KDED) << "displayButton: " << m_iteration;

    doApplyConfig(Generator::self()->displaySwitch(m_iteration));
}

void KScreenDaemon::lidClosedChanged(bool lidIsClosed)
{
    Q_UNUSED(lidIsClosed);
//     KDebug::Block genericConfig(" Lid closed");
//     qDebug() << "Lid is closed:" << lidIsClosed;
//     //If the laptop is closed, use ideal config WITHOUT saving it
//     if (lidIsClosed) {
//         setMonitorForChanges(false);
//         KScreen::Config::setConfig(Generator::self()->idealConfig());
//         return;
//     }
//
//     //If the lid is open, restore config (or generate a new one if needed
//     applyConfig();
}

void KScreenDaemon::outputConnectedChanged()
{
    if (!m_changeCompressor->isActive()) {
        m_changeCompressor->start();
    }

    resetDisplaySwitch();

    KScreen::Output *output = qobject_cast<KScreen::Output*>(sender());
    qCDebug(KSCREEN_KDED) << "outputConnectedChanged():" << output->name();

    if (output->isConnected()) {
        Q_EMIT outputConnected(output->name());

        if (!Serializer::configExists(m_monitoredConfig)) {
            Q_EMIT unknownOutputConnected(output->name());
        }
    }
}

void KScreenDaemon::monitorConnectedChange()
{
    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(const KScreen::OutputPtr &output, outputs) {
        connect(output.data(), &KScreen::Output::isConnectedChanged,
                this, &KScreenDaemon::outputConnectedChanged,
                Qt::UniqueConnection);
    }
}

void KScreenDaemon::setMonitorForChanges(bool enabled)
{
    if (m_monitoring == enabled) {
        return;
    }

    qCDebug(KSCREEN_KDED) << "Monitor for changes: " << enabled;
    m_monitoring = enabled;
    if (m_monitoring) {
        connect(KScreen::ConfigMonitor::instance(), &KScreen::ConfigMonitor::configurationChanged,
                this, &KScreenDaemon::configChanged, Qt::UniqueConnection);
    } else {
        disconnect(KScreen::ConfigMonitor::instance(), &KScreen::ConfigMonitor::configurationChanged,
                   this, &KScreenDaemon::configChanged);
    }
}

#include "daemon.moc"
<commit_msg>fix global shortcut<commit_after>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  This program 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 2                   *
 *  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 General Public License for more details.                                     *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "daemon.h"
#include "serializer.h"
#include "generator.h"
#include "device.h"
#include "kscreenadaptor.h"
#include "debug.h"

#include <QTimer>
#include <QAction>
#include <QShortcut>
#include <QLoggingCategory>

#include <KLocalizedString>
#include <KActionCollection>
#include <KPluginFactory>
#include <KGlobalAccel>

#include <kscreen/config.h>
#include <kscreen/configmonitor.h>
#include <kscreen/getconfigoperation.h>
#include <kscreen/setconfigoperation.h>

K_PLUGIN_FACTORY(KScreenDaemonFactory, registerPlugin<KScreenDaemon>();)

KScreenDaemon::KScreenDaemon(QObject* parent, const QList< QVariant >& )
 : KDEDModule(parent)
 , m_monitoredConfig(0)
 , m_iteration(0)
 , m_monitoring(false)
 , m_changeCompressor(new QTimer())
 , m_buttonTimer(new QTimer())
 , m_saveTimer(new QTimer())

{
    QMetaObject::invokeMethod(this, "requestConfig", Qt::QueuedConnection);
}

void KScreenDaemon::requestConfig()
{
    connect(new KScreen::GetConfigOperation, &KScreen::GetConfigOperation::finished,
            this, &KScreenDaemon::configReady);
}

void KScreenDaemon::configReady(KScreen::ConfigOperation* op)
{
    if (op->hasError()) {
        return;
    }

    m_monitoredConfig = qobject_cast<KScreen::GetConfigOperation*>(op)->config();
    qCDebug(KSCREEN_KDED) << "Config" << m_monitoredConfig.data() << "is ready";
    KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);

    init();
}

KScreenDaemon::~KScreenDaemon()
{
    delete m_changeCompressor;
    delete m_saveTimer;
    delete m_buttonTimer;

    Generator::destroy();
    Device::destroy();
}

void KScreenDaemon::init()
{
    KActionCollection *coll = new KActionCollection(this);
    QAction* action = coll->addAction(QStringLiteral("display"));
    action->setText(i18n("Switch Display" ));
    KGlobalAccel::self()->setGlobalShortcut(action, Qt::Key_Display);
    connect(action, &QAction::triggered, [&](bool) { displayButton(); });

    new KScreenAdaptor(this);

    m_buttonTimer->setInterval(300);
    m_buttonTimer->setSingleShot(true);
    connect(m_buttonTimer, &QTimer::timeout, this, &KScreenDaemon::applyGenericConfig);

    m_saveTimer->setInterval(300);
    m_saveTimer->setSingleShot(true);
    connect(m_saveTimer, &QTimer::timeout, this, &KScreenDaemon::saveCurrentConfig);

    m_changeCompressor->setInterval(10);
    m_changeCompressor->setSingleShot(true);
    connect(m_changeCompressor, &QTimer::timeout, this, &KScreenDaemon::applyConfig);

    connect(Device::self(), &Device::lidClosedChanged, this, &KScreenDaemon::lidClosedChanged);
    connect(Device::self(), &Device::resumingFromSuspend,
            [&]() {
                qCDebug(KSCREEN_KDED) << "Resumed from suspend, checking for screen changes";
                // We don't care about the result, we just want to force the backend
                // to query XRandR so that it will detect possible changes that happened
                // while the computer was suspended, and will emit the change events.
                new KScreen::GetConfigOperation(KScreen::GetConfigOperation::NoEDID, this);
            });

    connect(Generator::self(), &Generator::ready,
            this, &KScreenDaemon::applyConfig);

    Generator::self()->setCurrentConfig(m_monitoredConfig);
    monitorConnectedChange();
}

void KScreenDaemon::doApplyConfig(const KScreen::ConfigPtr& config)
{
    qCDebug(KSCREEN_KDED) << "doApplyConfig()";
    setMonitorForChanges(false);

    connect(new KScreen::SetConfigOperation(config), &KScreen::SetConfigOperation::finished,
            [&]() {
                qCDebug(KSCREEN_KDED) << "Config applied";
                setMonitorForChanges(true);
            });
}

void KScreenDaemon::applyConfig()
{
    qCDebug(KSCREEN_KDED) << "Applying config";
    if (Serializer::configExists(m_monitoredConfig)) {
        applyKnownConfig();
        return;
    }

    applyIdealConfig();
}

void KScreenDaemon::applyKnownConfig()
{
    const QString configId = Serializer::configId(m_monitoredConfig);
    qCDebug(KSCREEN_KDED) << "Applying known config" << configId;

    KScreen::ConfigPtr config = Serializer::config(m_monitoredConfig, configId);
    if (!KScreen::Config::canBeApplied(config)) {
        return applyIdealConfig();
    }

    doApplyConfig(config);
}

void KScreenDaemon::applyIdealConfig()
{
    qCDebug(KSCREEN_KDED) << "Applying ideal config";
    doApplyConfig(Generator::self()->idealConfig(m_monitoredConfig));
}

void KScreenDaemon::configChanged()
{
    qCDebug(KSCREEN_KDED) << "Change detected";
    // Reset timer, delay the writeback
    m_saveTimer->start();
}

void KScreenDaemon::saveCurrentConfig()
{
    qCDebug(KSCREEN_KDED) << "Saving current config to file";
    Serializer::saveConfig(m_monitoredConfig);
}

void KScreenDaemon::displayButton()
{
    qCDebug(KSCREEN_KDED) << "displayBtn triggered";
    if (m_buttonTimer->isActive()) {
        qCDebug(KSCREEN_KDED) << "Too fast, cowboy";
        return;
    }

    m_buttonTimer->start();
}

void KScreenDaemon::resetDisplaySwitch()
{
    qCDebug(KSCREEN_KDED) << "resetDisplaySwitch()";
    m_iteration = 0;
}

void KScreenDaemon::applyGenericConfig()
{
    if (m_iteration == 5) {
        m_iteration = 0;
    }

    m_iteration++;
    qCDebug(KSCREEN_KDED) << "displayButton: " << m_iteration;

    doApplyConfig(Generator::self()->displaySwitch(m_iteration));
}

void KScreenDaemon::lidClosedChanged(bool lidIsClosed)
{
    Q_UNUSED(lidIsClosed);
//     KDebug::Block genericConfig(" Lid closed");
//     qDebug() << "Lid is closed:" << lidIsClosed;
//     //If the laptop is closed, use ideal config WITHOUT saving it
//     if (lidIsClosed) {
//         setMonitorForChanges(false);
//         KScreen::Config::setConfig(Generator::self()->idealConfig());
//         return;
//     }
//
//     //If the lid is open, restore config (or generate a new one if needed
//     applyConfig();
}

void KScreenDaemon::outputConnectedChanged()
{
    if (!m_changeCompressor->isActive()) {
        m_changeCompressor->start();
    }

    resetDisplaySwitch();

    KScreen::Output *output = qobject_cast<KScreen::Output*>(sender());
    qCDebug(KSCREEN_KDED) << "outputConnectedChanged():" << output->name();

    if (output->isConnected()) {
        Q_EMIT outputConnected(output->name());

        if (!Serializer::configExists(m_monitoredConfig)) {
            Q_EMIT unknownOutputConnected(output->name());
        }
    }
}

void KScreenDaemon::monitorConnectedChange()
{
    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(const KScreen::OutputPtr &output, outputs) {
        connect(output.data(), &KScreen::Output::isConnectedChanged,
                this, &KScreenDaemon::outputConnectedChanged,
                Qt::UniqueConnection);
    }
}

void KScreenDaemon::setMonitorForChanges(bool enabled)
{
    if (m_monitoring == enabled) {
        return;
    }

    qCDebug(KSCREEN_KDED) << "Monitor for changes: " << enabled;
    m_monitoring = enabled;
    if (m_monitoring) {
        connect(KScreen::ConfigMonitor::instance(), &KScreen::ConfigMonitor::configurationChanged,
                this, &KScreenDaemon::configChanged, Qt::UniqueConnection);
    } else {
        disconnect(KScreen::ConfigMonitor::instance(), &KScreen::ConfigMonitor::configurationChanged,
                   this, &KScreenDaemon::configChanged);
    }
}

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


<commit_before>/*
 * VehicleControlDeviceImplementation.cpp
 *
 *  Created on: 10/04/2010
 *      Author: victor
 */

#include "VehicleControlDevice.h"
#include "server/zone/managers/objectcontroller/ObjectController.h"
#include "server/zone/objects/player/PlayerCreature.h"
#include "server/zone/objects/creature/VehicleObject.h"
#include "server/zone/ZoneServer.h"

void VehicleControlDeviceImplementation::generateObject(PlayerCreature* player) {
	if (player->getParent() != NULL)
		return;

	if (controlledObject->isInQuadTree())
		return;

	if (player->isInCombat() || player->isDead() || player->isIncapacitated())
		return;

	ZoneServer* zoneServer = getZoneServer();

	Locker clocker(controlledObject, player);

	controlledObject->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
	controlledObject->setCreatureLink(player);
	controlledObject->setControlDevice(_this);

	controlledObject->insertToZone(player->getZone());
	controlledObject->inflictDamage(player, 0, System::random(50), true);

	updateStatus(1);
}

void VehicleControlDeviceImplementation::storeObject(PlayerCreature* player) {
	if (controlledObject == NULL)
		return;

	if (!controlledObject->isInQuadTree())
		return;

	if (player->isRidingMount()) {
		player->executeObjectControllerAction(String("dismount").hashCode());

		if (player->isRidingMount())
			return;
	}

	controlledObject->removeFromZone();
	controlledObject->setCreatureLink(NULL);

	updateStatus(0);
}

void VehicleControlDeviceImplementation::destroyObjectFromDatabase(bool destroyContainedObjects) {
	if (controlledObject != NULL) {
		controlledObject->destroyObjectFromDatabase(true);
	}

	IntangibleObjectImplementation::destroyObjectFromDatabase(destroyContainedObjects);
}

int VehicleControlDeviceImplementation::canBeDestroyed(PlayerCreature* player) {
	if (controlledObject != NULL) {
		if (controlledObject->isInQuadTree())
			return 1;
	}

	return IntangibleObjectImplementation::canBeDestroyed(player);
}
<commit_msg>[fixed] 0000299: Store vehicule x then you unmount vehicule y<commit_after>/*
 * VehicleControlDeviceImplementation.cpp
 *
 *  Created on: 10/04/2010
 *      Author: victor
 */

#include "VehicleControlDevice.h"
#include "server/zone/managers/objectcontroller/ObjectController.h"
#include "server/zone/objects/player/PlayerCreature.h"
#include "server/zone/objects/creature/VehicleObject.h"
#include "server/zone/ZoneServer.h"

void VehicleControlDeviceImplementation::generateObject(PlayerCreature* player) {
	if (player->getParent() != NULL)
		return;

	if (controlledObject->isInQuadTree())
		return;

	if (player->isInCombat() || player->isDead() || player->isIncapacitated())
		return;

	ManagedReference<SceneObject*> datapad = player->getSlottedObject("datapad");

	if (datapad == NULL)
		return;

	for (int i = 0; i < datapad->getContainerObjectsSize(); ++i) {
		ManagedReference<SceneObject*> object = datapad->getContainerObject(i);

		if (object->isControlDevice()) {
			ControlDevice* device = (ControlDevice*) object.get();

			ManagedReference<SceneObject*> vehicle = device->getControlledObject();

			if (vehicle != NULL && vehicle->isInQuadTree()) {
				player->sendSystemMessage("You can only generate one vehicle"); // TODO:find appropiate string id
				return;
			}
		}
	}

	ZoneServer* zoneServer = getZoneServer();

	Locker clocker(controlledObject, player);

	controlledObject->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
	controlledObject->setCreatureLink(player);
	controlledObject->setControlDevice(_this);

	controlledObject->insertToZone(player->getZone());
	controlledObject->inflictDamage(player, 0, System::random(50), true);

	updateStatus(1);
}

void VehicleControlDeviceImplementation::storeObject(PlayerCreature* player) {
	if (controlledObject == NULL)
		return;

	if (!controlledObject->isInQuadTree())
		return;

	if (player->isRidingMount()) {
		player->executeObjectControllerAction(String("dismount").hashCode());

		if (player->isRidingMount())
			return;
	}

	controlledObject->removeFromZone();
	controlledObject->setCreatureLink(NULL);

	updateStatus(0);
}

void VehicleControlDeviceImplementation::destroyObjectFromDatabase(bool destroyContainedObjects) {
	if (controlledObject != NULL) {
		controlledObject->destroyObjectFromDatabase(true);
	}

	IntangibleObjectImplementation::destroyObjectFromDatabase(destroyContainedObjects);
}

int VehicleControlDeviceImplementation::canBeDestroyed(PlayerCreature* player) {
	if (controlledObject != NULL) {
		if (controlledObject->isInQuadTree())
			return 1;
	}

	return IntangibleObjectImplementation::canBeDestroyed(player);
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2016 Liav Turkia

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <MACE/Utility/DynamicLibrary.h>
#include <MACE/Core/System.h>

#ifdef MACE_POSIX
#	include <dlfcn.h>
#endif//MACE_POSIX

namespace mc {
	DynamicLibrary DynamicLibrary::getRunningProcess() {
		DynamicLibrary runningProcess = DynamicLibrary();

#ifdef MACE_WINAPI
		runningProcess.dll = GetModuleHandle(nullptr);
#elif defined(MACE_POSIX)
		//the NULL macro is used instead of nullptr because dlopen accepts an argument of 0 specifically
		//it needs to be an integer, not a pointer value.
		runningProcess.dll = dlopen(NULL, RTLD_GLOBAL | RTLD_LAZY);
#endif

		if( runningProcess.dll == nullptr ) {
#ifdef MACE_POSIX
			const char* errorMessage = dlerror();
#else
			constexpr char* errorMessage = "Handle to running process was nullptr";
#endif

			throw NullPointerError("Internal Error: " + std::string(errorMessage));
		}

		runningProcess.created = true;

		os::checkError(__LINE__, __FILE__, "Error retrieving current running process as dynamic library");

		return runningProcess;
	}

	DynamicLibrary::~DynamicLibrary() {
		if( isCreated() ) {
			destroy();
		}
	}

	DynamicLibrary::DynamicLibrary() {}

	DynamicLibrary::DynamicLibrary(const std::string & path) : DynamicLibrary(path.c_str()) {}

	DynamicLibrary::DynamicLibrary(const char * path) : DynamicLibrary() {
		init(path);
	}

	void DynamicLibrary::init(const std::string & path) {
		init(path.c_str());
	}

	void DynamicLibrary::init(const char * path) {
		if( isCreated() ) {
			throw InitializationFailedError("Can\'t reinitialize a DynamicLibrary object!");
		}

#ifdef MACE_WINAPI
		dll = LoadLibrary(path);
#elif defined(MACE_POSIX)
		dll = dlopen(path, RTLD_LAZY);
#endif

		if( dll == nullptr ) {
#ifdef MACE_POSIX
			const char* errorMessage = dlerror();
#else
			constexpr char* errorMessage = "Library handle was nullptr";
#endif

			os::checkError(__LINE__, __FILE__, "Attempt to load library " + std::string(path) + " returned a nullptr: " + std::string(errorMessage));

			throw FileNotFoundError("Unable to load dynamic library: " + std::string(path) + ": " + std::string(errorMessage));
		}

		created = true;

		os::checkError(__LINE__, __FILE__, "Error creating dynamic library at " + std::string(path));
	}

	void DynamicLibrary::destroy() {
		if( !isCreated() ) {
			throw AssertionFailedError("Can\'t destroy an uncreated DynamicLibrary");
		}

		if( dll == nullptr ) {
			throw NullPointerError("Can\'t destroy DynamicLibrary: internal handle was nullptr. Did initialization fail?");
		}

#ifdef MACE_WINAPI
		if( !FreeLibrary(dll) ) {
			os::checkError(__LINE__, __FILE__, "Destruction of dynamic library failed");

			throw AssertionFailedError("Destruction of dynamic library failed");
		}
#elif defined(MACE_POSIX)
		int result = dlclose(dll);

		if( result != 0 ) {
			const char* errorMessage = dlerror();

			os::checkError(__LINE__, __FILE__, "Failed to close dynamic library handle with result " + std::to_string(result) + ": " + std::string(errorMessage));

			throw AssertionFailedError("Failed to close dynamic library handle with result "+std::to_string(result)+": "+std::string(errorMessage));
		}
#endif

		created = false;

		os::checkError(__LINE__, __FILE__, "Error destroying dynamic library");
	}

	void * DynamicLibrary::getFunction(const std::string & name) {
		return getFunction(name.c_str());
	}

	void * DynamicLibrary::getFunction(const char * name) {
		if( !isCreated() ) {
			throw InitializationFailedError("Can\'t load a function symbol from an unitialized dynamic library");
		}

#ifdef MACE_WINAPI
		void* extractedSymbol = GetProcAddress(dll, name);
#elif defined(MACE_POSIX)
		void* extractedSymbol = dlsym(dll, name);
#endif

		if( extractedSymbol == nullptr ) {
#ifdef MACE_POSIX
			const char* errorMessage = dlerror();
#else
			constexpr char* errorMessage = "Returned function pointer was null pointer";
#endif

			os::checkError(__LINE__, __FILE__, "Attempt to load symbol " + std::string(name) + " returned a nullptr: " + std::string(errorMessage));

			throw NullPointerError("Unable to load symbol from dynamic library: " + std::string(name) + ": "+std::string(errorMessage));
		}

		os::checkError(__LINE__, __FILE__, "Error extracting symbol " + std::string(name) + " from dynamic library");

		return extractedSymbol;
	}

	bool DynamicLibrary::isCreated() const {
		return created;
	}
}//mc
<commit_msg>Improved error messages on dynamic library<commit_after>/*
The MIT License (MIT)

Copyright (c) 2016 Liav Turkia

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <MACE/Utility/DynamicLibrary.h>
#include <MACE/Core/System.h>

#ifdef MACE_POSIX
#	include <dlfcn.h>
#endif//MACE_POSIX

namespace mc {
	DynamicLibrary DynamicLibrary::getRunningProcess() {
		DynamicLibrary runningProcess = DynamicLibrary();

#ifdef MACE_WINAPI
		runningProcess.dll = GetModuleHandle(nullptr);
#elif defined(MACE_POSIX)
		//the NULL macro is used instead of nullptr because dlopen accepts an argument of 0 specifically
		//it needs to be an integer, not a pointer value.
		runningProcess.dll = dlopen(NULL, RTLD_LOCAL | RTLD_LAZY);
#endif

#ifdef MACE_POSIX
		char* errorMessage = dlerror();

		if( errorMessage == nullptr ) {
			errorMessage = "No error detected by POSIX";
		}
#else
		constexpr char* errorMessage = "Handle to running process was nullptr";
#endif

		if( runningProcess.dll == nullptr ) {
			throw NullPointerError("Internal Error: " + std::string(errorMessage));
		}

		runningProcess.created = true;

		os::checkError(__LINE__, __FILE__, "Error retrieving current running process as dynamic library: " + std::string(errorMessage));

		return runningProcess;
	}

	DynamicLibrary::~DynamicLibrary() {
		if( isCreated() ) {
			destroy();
		}
	}

	DynamicLibrary::DynamicLibrary() {}

	DynamicLibrary::DynamicLibrary(const std::string & path) : DynamicLibrary(path.c_str()) {}

	DynamicLibrary::DynamicLibrary(const char * path) : DynamicLibrary() {
		init(path);
	}

	void DynamicLibrary::init(const std::string & path) {
		init(path.c_str());
	}

	void DynamicLibrary::init(const char * path) {
		if( isCreated() ) {
			throw InitializationFailedError("Can\'t reinitialize a DynamicLibrary object!");
		}

#ifdef MACE_WINAPI
		dll = LoadLibrary(path);
#elif defined(MACE_POSIX)
		dll = dlopen(path, RTLD_LAZY);
#endif

#ifdef MACE_POSIX
		char* errorMessage = dlerror();

		if( errorMessage == nullptr ) {
			errorMessage = "No message detected from POSIX";
		}
#else
		constexpr char* errorMessage = "Library handle was nullptr";
#endif

		if( dll == nullptr ) {
			os::checkError(__LINE__, __FILE__, "Attempt to load library " + std::string(path) + " returned a nullptr: " + std::string(errorMessage));

			throw FileNotFoundError("Dynamic library not found: " + std::string(path) + ": " + std::string(errorMessage));
		}

		created = true;

		os::checkError(__LINE__, __FILE__, "Error creating dynamic library at " + std::string(path) + ": " + std::string(errorMessage));
	}

	void DynamicLibrary::destroy() {
		if( !isCreated() ) {
			throw AssertionFailedError("Can\'t destroy an uncreated DynamicLibrary");
		}

		if( dll == nullptr ) {
			throw NullPointerError("Can\'t destroy DynamicLibrary: internal handle was nullptr. Did initialization fail?");
		}

#ifdef MACE_WINAPI
		if( !FreeLibrary(dll) ) {
			os::checkError(__LINE__, __FILE__, "Destruction of dynamic library failed");

			throw AssertionFailedError("Destruction of dynamic library failed");
		}
#elif defined(MACE_POSIX)
		int result = dlclose(dll);

		if( result != 0 ) {
			const char* errorMessage = dlerror();

			os::checkError(__LINE__, __FILE__, "Failed to close dynamic library handle with result " + std::to_string(result) + ": " + std::string(errorMessage));

			throw AssertionFailedError("Failed to close dynamic library handle with result " + std::to_string(result) + ": " + std::string(errorMessage));
		}
#endif

		created = false;

		os::checkError(__LINE__, __FILE__, "Error destroying dynamic library");
	}

	void * DynamicLibrary::getFunction(const std::string & name) {
		return getFunction(name.c_str());
	}

	void * DynamicLibrary::getFunction(const char * name) {
		if( !isCreated() ) {
			throw InitializationFailedError("Can\'t load a function symbol from an unitialized dynamic library");
		}

#ifdef MACE_WINAPI
		void* extractedSymbol = GetProcAddress(dll, name);
#elif defined(MACE_POSIX)
		void* extractedSymbol = dlsym(dll, name);
#endif

		if( extractedSymbol == nullptr ) {
#ifdef MACE_POSIX
			const char* errorMessage = dlerror();
#else
			constexpr char* errorMessage = "Returned function pointer was null pointer";
#endif

			os::checkError(__LINE__, __FILE__, "Attempt to load symbol " + std::string(name) + " returned a nullptr: " + std::string(errorMessage));

			throw NullPointerError("Unable to load symbol from dynamic library: " + std::string(name) + ": " + std::string(errorMessage));
		}

		os::checkError(__LINE__, __FILE__, "Error extracting symbol " + std::string(name) + " from dynamic library");

		return extractedSymbol;
		}

	bool DynamicLibrary::isCreated() const {
		return created;
	}
	}//mc
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "architec.h"
# include  "entity.h"
# include  "expression.h"
# include  "sequential.h"
# include  "subprogram.h"
# include  <typeinfo>
# include  <cassert>

int Architecture::elaborate(Entity*entity)
{
      int errors = 0;

	// Constant assignments in the architecture get their types
	// from the constant declaration itself. Elaborate the value
	// expression with the declared type.

      for (map<perm_string,struct const_t*>::iterator cur = use_constants_.begin()
		 ; cur != use_constants_.end() ; ++cur) {
	    cur->second->val->elaborate_expr(entity, this, cur->second->typ);
      }
      for (map<perm_string,struct const_t*>::iterator cur = cur_constants_.begin()
		 ; cur != cur_constants_.end() ; ++cur) {
	    cur->second->val->elaborate_expr(entity, this, cur->second->typ);
      }

        // Elaborate initializer expressions for signals & variables
      for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
		 ; cur != old_signals_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }
      for (map<perm_string,Signal*>::iterator cur = new_signals_.begin()
		 ; cur != new_signals_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }
      for (map<perm_string,Variable*>::iterator cur = old_variables_.begin()
		 ; cur != old_variables_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }
      for (map<perm_string,Variable*>::iterator cur = new_variables_.begin()
		 ; cur != new_variables_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }

	// Elaborate subprograms
      for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
		 ; cur != cur_subprograms_.end() ; ++cur) {
	    const SubHeaderList& subp_list = cur->second;

	    for(SubHeaderList::const_iterator it = subp_list.begin();
			it != subp_list.end(); ++it) {
        	errors += (*it)->elaborate();
	    }
      }
	// Create 'initial' and 'final' blocks for implicit
	// initalization and clean-up actions
      if(!initializers_.empty())
	    statements_.push_front(new InitialStatement(&initializers_));

      if(!finalizers_.empty())
	    statements_.push_front(new FinalStatement(&finalizers_));

      for (list<Architecture::Statement*>::iterator cur = statements_.begin()
		 ; cur != statements_.end() ; ++cur) {

	    int cur_errors = (*cur)->elaborate(entity, this);
	    errors += cur_errors;
      }

      if (errors > 0) {
	    cerr << errors << " errors in "
		 << name_ << " architecture of "
		 << entity->get_name() << "." << endl;
      }

      return errors;
}

int Architecture::Statement::elaborate(Entity*, Architecture*)
{
      return 0;
}

int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

      ComponentBase*base = arc->find_component(cname_);
      if (base == 0) {
	    cerr << get_fileline() << ": error: No component declaration"
		 << " for instance " << iname_
		 << " of " << cname_ << "." << endl;
	    return 1;
      }

      arc->set_cur_component(this);

      for (map<perm_string,Expression*>::const_iterator cur = generic_map_.begin()
		 ; cur != generic_map_.end() ; ++cur) {
	      // check if generic from component instantiation
	      // exists in the component declaration
	    const InterfacePort*iparm = base->find_generic(cur->first);
	    if (iparm == 0) {
		  cerr << get_fileline() << ": warning: No generic " << cur->first
		       << " in component " << cname_ << "." << endl;
		  continue;
	    }

	    ExpName* tmp;
	    if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
		  errors += tmp->elaborate_rval(ent, arc, iparm);

	    if (cur->second)
		  errors += cur->second->elaborate_expr(ent, arc, iparm->type);
      }

      for (map<perm_string,Expression*>::const_iterator cur = port_map_.begin()
		 ; cur != port_map_.end() ; ++cur) {
	      // check if a port from component instantiation
	      // exists in the component declaration
	    const InterfacePort*iport = base->find_port(cur->first);
	    if (iport == 0) {
		  cerr << get_fileline() << ": error: No port " << cur->first
		       << " in component " << cname_ << "." << endl;
		  errors += 1;
		  continue;
	    }

	    ExpName* tmp;
	    if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
		  errors += tmp->elaborate_rval(ent, arc, iport);
	      /* It is possible for the port to be explicitly
		 unconnected. In that case, the Expression will be nil */

	    if (cur->second)
		  cur->second->elaborate_expr(ent, arc, iport->type);
      }

      arc->set_cur_component(NULL);

      return errors;
}

int GenerateStatement::elaborate_statements(Entity*ent, Architecture*arc)
{
      int errors = 0;
      for (list<Architecture::Statement*>::iterator cur = statements_.begin()
		 ; cur != statements_.end() ; ++cur) {
	    Architecture::Statement*curp = *cur;
	    errors += curp->elaborate(ent, arc);
      }
      return errors;
}

int ForGenerate::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;
      arc->push_genvar_type(genvar_, lsb_->probe_type(ent, arc));
      errors += elaborate_statements(ent, arc);
      arc->pop_genvar_type();
      return errors;
}

int IfGenerate::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;
      errors += elaborate_statements(ent, arc);
      return errors;
}

/*
 * This method attempts to rewrite the process content as an
 * always-@(n-edge <expr>) version of the same statement. This makes
 * for a more natural translation to Verilog, if it comes to that.
 */
int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
{
	// If there are multiple sensitivity expressions, I give up.
      if (sensitivity_list_.size() != 1)
	    return -1;

	// If there are multiple statements, I give up.
      if (stmt_list().size() != 1)
	    return -1;

      Expression*se = sensitivity_list_.front();
      SequentialStmt*stmt_raw = stmt_list().front();

	// If the statement is not an if-statement, I give up.
      IfSequential*stmt = dynamic_cast<IfSequential*> (stmt_raw);
      if (stmt == 0)
	    return -1;

	// If the "if" statement has a false clause, then give up.
      if (stmt->false_size() != 0)
	    return -1;

      const Expression*ce_raw = stmt->peek_condition();

	// Here we expect the condition to be
	//    <name>'event AND <name>='1'.
	// So if ce_raw is not a logical AND, I give up.
      const ExpLogical*ce = dynamic_cast<const ExpLogical*> (ce_raw);
      if (ce == 0)
	    return -1;
      if (ce->logic_fun() != ExpLogical::AND)
	    return -1;

      const Expression*op1_raw = ce->peek_operand1();
      const Expression*op2_raw = ce->peek_operand2();
      if (dynamic_cast<const ExpAttribute*>(op2_raw)) {
	    const Expression*tmp = op1_raw;
	    op1_raw = op2_raw;
	    op2_raw = tmp;
      }

	// If operand1 is not an 'event attribute, I give up.
      const ExpObjAttribute*op1 = dynamic_cast<const ExpObjAttribute*>(op1_raw);
      if (op1 == 0)
	    return -1;
      if (op1->peek_attribute() != "event")
	    return -1;

      const ExpRelation*op2 = dynamic_cast<const ExpRelation*>(op2_raw);
      if (op2 == 0)
	    return -1;
      if (op2->relation_fun() != ExpRelation::EQ)
	    return -1;

      const Expression*op2a_raw = op2->peek_operand1();
      const Expression*op2b_raw = op2->peek_operand2();

      if (dynamic_cast<const ExpCharacter*>(op2a_raw)) {
	    const Expression*tmp = op2b_raw;
	    op2b_raw = op2a_raw;
	    op2a_raw = tmp;
      }

      if (! se->symbolic_compare(op1->peek_base()))
	    return -1;

      const ExpCharacter*op2b = dynamic_cast<const ExpCharacter*>(op2b_raw);
      if (op2b->value() != '1' && op2b->value() != '0')
	    return -1;

	// We've matched this pattern:
	//   process (<se>) if (<se>'event and <se> = <op2b>) then ...
	// And we can convert it to:
	//   always @(<N>edge <se>) ...

	// Replace the sensitivity expression with an edge
	// expression. The ExpEdge expression signals that this is an
	// always-@(edge) statement.
      ExpEdge*edge = new ExpEdge(op2b->value()=='1'? ExpEdge::POSEDGE : ExpEdge::NEGEDGE, se);
      assert(sensitivity_list_.size() == 1);
      sensitivity_list_.pop_front();
      sensitivity_list_.push_front(edge);

	// Replace the statement with the body of the always
	// statement, which is the true clause of the top "if"
	// statement. There should be no "else" clause.
      assert(stmt_list().size() == 1);
      stmt_list().pop_front();

      stmt->extract_true(stmt_list());

      delete stmt;

      return 0;
}

int StatementList::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

      for (std::list<SequentialStmt*>::iterator it = statements_.begin();
              it != statements_.end(); ++it) {
            errors += (*it)->elaborate(ent, arc);
      }

      return errors;
}

/*
 * Change the "process (<expr>) <stmt>" into "always @(<expr>) ..."
 */
int ProcessStatement::extract_anyedge_(Entity*, Architecture*)
{
      vector<Expression*> se;
      while (! sensitivity_list_.empty()) {
	    se.push_back(sensitivity_list_.front());
	    sensitivity_list_.pop_front();
      }

      for (size_t idx = 0 ; idx < se.size() ; idx += 1) {
	    ExpEdge*edge = new ExpEdge(ExpEdge::ANYEDGE, se[idx]);
	    FILE_NAME(edge, se[idx]);
	    sensitivity_list_.push_back(edge);
      }

      return 0;
}

int ProcessStatement::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

      if (rewrite_as_always_edge_(ent, arc) >= 0) {
	    extract_anyedge_(ent, arc);
      }

      StatementList::elaborate(ent, arc);

      return errors;
}

int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

	// Elaborate the l-value expression.
      errors += lval_->elaborate_lval(ent, arc, false);

	// The elaborate_lval should have resolved the type of the
	// l-value expression. We'll use that type to elaborate the
	// r-value.
      const VType*lval_type = lval_->peek_type();
      if (lval_type == 0) {
	    if (errors == 0) {
		  errors += 1;
		  cerr << get_fileline() << ": error: Unable to calculate type for l-value expression." << endl;
	    }
	    return errors;
      }

      for (list<Expression*>::iterator cur = rval_.begin()
		 ; cur != rval_.end() ; ++cur) {
	    errors += (*cur)->elaborate_expr(ent, arc, lval_type);
      }

      return errors;
}

int CondSignalAssignment::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

        // Visitor to extract signal names occuring in the conditional
        // statements to create the sensitivity list
      struct name_extractor_t : public ExprVisitor {
          name_extractor_t(list<const ExpName*>& name_list)
              : name_list_(name_list) {}
          void operator() (Expression*s) {
              if(const ExpName*name = dynamic_cast<const ExpName*>(s))
                  name_list_.push_back(name);
          }

          private:
            list<const ExpName*>& name_list_;
      } name_extractor(sens_list_);

        // Elaborate the l-value expression.
      errors += lval_->elaborate_lval(ent, arc, true);

        // The elaborate_lval should have resolved the type of the
        // l-value expression. We'll use that type to elaborate the
        // r-value.
      const VType*lval_type = lval_->peek_type();
      if (lval_type == 0) {
          if (errors == 0) {
              errors += 1;
              cerr << get_fileline()
                   << ": error: Unable to calculate type for l-value expression."
                   << endl;
          }
          return errors;
      }

      for(list<ExpConditional::case_t*>::iterator it = options_.begin();
              it != options_.end(); ++it) {
          ExpConditional::case_t*cas = (*it);
          cas->elaborate_expr(ent, arc, lval_type);
          cas->visit(name_extractor);
      }

      return errors;
}
<commit_msg>vhdlpp: Fixed a crash in case of dynamic_cast failure.<commit_after>/*
 * Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "architec.h"
# include  "entity.h"
# include  "expression.h"
# include  "sequential.h"
# include  "subprogram.h"
# include  <typeinfo>
# include  <cassert>

int Architecture::elaborate(Entity*entity)
{
      int errors = 0;

	// Constant assignments in the architecture get their types
	// from the constant declaration itself. Elaborate the value
	// expression with the declared type.

      for (map<perm_string,struct const_t*>::iterator cur = use_constants_.begin()
		 ; cur != use_constants_.end() ; ++cur) {
	    cur->second->val->elaborate_expr(entity, this, cur->second->typ);
      }
      for (map<perm_string,struct const_t*>::iterator cur = cur_constants_.begin()
		 ; cur != cur_constants_.end() ; ++cur) {
	    cur->second->val->elaborate_expr(entity, this, cur->second->typ);
      }

        // Elaborate initializer expressions for signals & variables
      for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
		 ; cur != old_signals_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }
      for (map<perm_string,Signal*>::iterator cur = new_signals_.begin()
		 ; cur != new_signals_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }
      for (map<perm_string,Variable*>::iterator cur = old_variables_.begin()
		 ; cur != old_variables_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }
      for (map<perm_string,Variable*>::iterator cur = new_variables_.begin()
		 ; cur != new_variables_.end() ; ++cur) {
	    cur->second->elaborate(entity, this);
      }

	// Elaborate subprograms
      for (map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin()
		 ; cur != cur_subprograms_.end() ; ++cur) {
	    const SubHeaderList& subp_list = cur->second;

	    for(SubHeaderList::const_iterator it = subp_list.begin();
			it != subp_list.end(); ++it) {
        	errors += (*it)->elaborate();
	    }
      }
	// Create 'initial' and 'final' blocks for implicit
	// initalization and clean-up actions
      if(!initializers_.empty())
	    statements_.push_front(new InitialStatement(&initializers_));

      if(!finalizers_.empty())
	    statements_.push_front(new FinalStatement(&finalizers_));

      for (list<Architecture::Statement*>::iterator cur = statements_.begin()
		 ; cur != statements_.end() ; ++cur) {

	    int cur_errors = (*cur)->elaborate(entity, this);
	    errors += cur_errors;
      }

      if (errors > 0) {
	    cerr << errors << " errors in "
		 << name_ << " architecture of "
		 << entity->get_name() << "." << endl;
      }

      return errors;
}

int Architecture::Statement::elaborate(Entity*, Architecture*)
{
      return 0;
}

int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

      ComponentBase*base = arc->find_component(cname_);
      if (base == 0) {
	    cerr << get_fileline() << ": error: No component declaration"
		 << " for instance " << iname_
		 << " of " << cname_ << "." << endl;
	    return 1;
      }

      arc->set_cur_component(this);

      for (map<perm_string,Expression*>::const_iterator cur = generic_map_.begin()
		 ; cur != generic_map_.end() ; ++cur) {
	      // check if generic from component instantiation
	      // exists in the component declaration
	    const InterfacePort*iparm = base->find_generic(cur->first);
	    if (iparm == 0) {
		  cerr << get_fileline() << ": warning: No generic " << cur->first
		       << " in component " << cname_ << "." << endl;
		  continue;
	    }

	    ExpName* tmp;
	    if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
		  errors += tmp->elaborate_rval(ent, arc, iparm);

	    if (cur->second)
		  errors += cur->second->elaborate_expr(ent, arc, iparm->type);
      }

      for (map<perm_string,Expression*>::const_iterator cur = port_map_.begin()
		 ; cur != port_map_.end() ; ++cur) {
	      // check if a port from component instantiation
	      // exists in the component declaration
	    const InterfacePort*iport = base->find_port(cur->first);
	    if (iport == 0) {
		  cerr << get_fileline() << ": error: No port " << cur->first
		       << " in component " << cname_ << "." << endl;
		  errors += 1;
		  continue;
	    }

	    ExpName* tmp;
	    if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
		  errors += tmp->elaborate_rval(ent, arc, iport);
	      /* It is possible for the port to be explicitly
		 unconnected. In that case, the Expression will be nil */

	    if (cur->second)
		  cur->second->elaborate_expr(ent, arc, iport->type);
      }

      arc->set_cur_component(NULL);

      return errors;
}

int GenerateStatement::elaborate_statements(Entity*ent, Architecture*arc)
{
      int errors = 0;
      for (list<Architecture::Statement*>::iterator cur = statements_.begin()
		 ; cur != statements_.end() ; ++cur) {
	    Architecture::Statement*curp = *cur;
	    errors += curp->elaborate(ent, arc);
      }
      return errors;
}

int ForGenerate::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;
      arc->push_genvar_type(genvar_, lsb_->probe_type(ent, arc));
      errors += elaborate_statements(ent, arc);
      arc->pop_genvar_type();
      return errors;
}

int IfGenerate::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;
      errors += elaborate_statements(ent, arc);
      return errors;
}

/*
 * This method attempts to rewrite the process content as an
 * always-@(n-edge <expr>) version of the same statement. This makes
 * for a more natural translation to Verilog, if it comes to that.
 */
int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
{
	// If there are multiple sensitivity expressions, I give up.
      if (sensitivity_list_.size() != 1)
	    return -1;

	// If there are multiple statements, I give up.
      if (stmt_list().size() != 1)
	    return -1;

      Expression*se = sensitivity_list_.front();
      SequentialStmt*stmt_raw = stmt_list().front();

	// If the statement is not an if-statement, I give up.
      IfSequential*stmt = dynamic_cast<IfSequential*> (stmt_raw);
      if (stmt == 0)
	    return -1;

	// If the "if" statement has a false clause, then give up.
      if (stmt->false_size() != 0)
	    return -1;

      const Expression*ce_raw = stmt->peek_condition();

	// Here we expect the condition to be
	//    <name>'event AND <name>='1'.
	// So if ce_raw is not a logical AND, I give up.
      const ExpLogical*ce = dynamic_cast<const ExpLogical*> (ce_raw);
      if (ce == 0)
	    return -1;
      if (ce->logic_fun() != ExpLogical::AND)
	    return -1;

      const Expression*op1_raw = ce->peek_operand1();
      const Expression*op2_raw = ce->peek_operand2();
      if (dynamic_cast<const ExpAttribute*>(op2_raw)) {
	    const Expression*tmp = op1_raw;
	    op1_raw = op2_raw;
	    op2_raw = tmp;
      }

	// If operand1 is not an 'event attribute, I give up.
      const ExpObjAttribute*op1 = dynamic_cast<const ExpObjAttribute*>(op1_raw);
      if (op1 == 0)
	    return -1;
      if (op1->peek_attribute() != "event")
	    return -1;

      const ExpRelation*op2 = dynamic_cast<const ExpRelation*>(op2_raw);
      if (op2 == 0)
	    return -1;
      if (op2->relation_fun() != ExpRelation::EQ)
	    return -1;

      const Expression*op2a_raw = op2->peek_operand1();
      const Expression*op2b_raw = op2->peek_operand2();

      if (dynamic_cast<const ExpCharacter*>(op2a_raw)) {
	    const Expression*tmp = op2b_raw;
	    op2b_raw = op2a_raw;
	    op2a_raw = tmp;
      }

      if (! se->symbolic_compare(op1->peek_base()))
	    return -1;

      const ExpCharacter*op2b = dynamic_cast<const ExpCharacter*>(op2b_raw);
      if (op2b == 0)
	    return -1;
      if (op2b->value() != '1' && op2b->value() != '0')
	    return -1;

	// We've matched this pattern:
	//   process (<se>) if (<se>'event and <se> = <op2b>) then ...
	// And we can convert it to:
	//   always @(<N>edge <se>) ...

	// Replace the sensitivity expression with an edge
	// expression. The ExpEdge expression signals that this is an
	// always-@(edge) statement.
      ExpEdge*edge = new ExpEdge(op2b->value()=='1'? ExpEdge::POSEDGE : ExpEdge::NEGEDGE, se);
      assert(sensitivity_list_.size() == 1);
      sensitivity_list_.pop_front();
      sensitivity_list_.push_front(edge);

	// Replace the statement with the body of the always
	// statement, which is the true clause of the top "if"
	// statement. There should be no "else" clause.
      assert(stmt_list().size() == 1);
      stmt_list().pop_front();

      stmt->extract_true(stmt_list());

      delete stmt;

      return 0;
}

int StatementList::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

      for (std::list<SequentialStmt*>::iterator it = statements_.begin();
              it != statements_.end(); ++it) {
            errors += (*it)->elaborate(ent, arc);
      }

      return errors;
}

/*
 * Change the "process (<expr>) <stmt>" into "always @(<expr>) ..."
 */
int ProcessStatement::extract_anyedge_(Entity*, Architecture*)
{
      vector<Expression*> se;
      while (! sensitivity_list_.empty()) {
	    se.push_back(sensitivity_list_.front());
	    sensitivity_list_.pop_front();
      }

      for (size_t idx = 0 ; idx < se.size() ; idx += 1) {
	    ExpEdge*edge = new ExpEdge(ExpEdge::ANYEDGE, se[idx]);
	    FILE_NAME(edge, se[idx]);
	    sensitivity_list_.push_back(edge);
      }

      return 0;
}

int ProcessStatement::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

      if (rewrite_as_always_edge_(ent, arc) >= 0) {
	    extract_anyedge_(ent, arc);
      }

      StatementList::elaborate(ent, arc);

      return errors;
}

int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

	// Elaborate the l-value expression.
      errors += lval_->elaborate_lval(ent, arc, false);

	// The elaborate_lval should have resolved the type of the
	// l-value expression. We'll use that type to elaborate the
	// r-value.
      const VType*lval_type = lval_->peek_type();
      if (lval_type == 0) {
	    if (errors == 0) {
		  errors += 1;
		  cerr << get_fileline() << ": error: Unable to calculate type for l-value expression." << endl;
	    }
	    return errors;
      }

      for (list<Expression*>::iterator cur = rval_.begin()
		 ; cur != rval_.end() ; ++cur) {
	    errors += (*cur)->elaborate_expr(ent, arc, lval_type);
      }

      return errors;
}

int CondSignalAssignment::elaborate(Entity*ent, Architecture*arc)
{
      int errors = 0;

        // Visitor to extract signal names occuring in the conditional
        // statements to create the sensitivity list
      struct name_extractor_t : public ExprVisitor {
          name_extractor_t(list<const ExpName*>& name_list)
              : name_list_(name_list) {}
          void operator() (Expression*s) {
              if(const ExpName*name = dynamic_cast<const ExpName*>(s))
                  name_list_.push_back(name);
          }

          private:
            list<const ExpName*>& name_list_;
      } name_extractor(sens_list_);

        // Elaborate the l-value expression.
      errors += lval_->elaborate_lval(ent, arc, true);

        // The elaborate_lval should have resolved the type of the
        // l-value expression. We'll use that type to elaborate the
        // r-value.
      const VType*lval_type = lval_->peek_type();
      if (lval_type == 0) {
          if (errors == 0) {
              errors += 1;
              cerr << get_fileline()
                   << ": error: Unable to calculate type for l-value expression."
                   << endl;
          }
          return errors;
      }

      for(list<ExpConditional::case_t*>::iterator it = options_.begin();
              it != options_.end(); ++it) {
          ExpConditional::case_t*cas = (*it);
          cas->elaborate_expr(ent, arc, lval_type);
          cas->visit(name_extractor);
      }

      return errors;
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/PolyLine.h"
#include "cinder/gl/gl.h"
#include "cinder/gl/VboMesh.h"
#include "cinder/Rand.h"
#include "cinder/Path2d.h"
#include "cinder/Timer.h"
#include "cinder/Log.h"

using namespace ci;
using namespace ci::app;
using namespace std;

const float cCircleRadius = 40;
const float cGridStep = cCircleRadius * 2.2f;

/**
 ConvenienceDrawingMethodsApp:

 Demonstrates most of Cinder's convenience drawing methods.
 These are not the most CPU/GPU-efficient methods of drawing, but they
 are a quick way to get something on screen.
 */
class ConvenienceDrawingMethodsApp : public App {
  public:
	void setup() override;
	void keyDown( KeyEvent event ) override;
	void update() override;
	void draw() override;
  private:
	void drawBasicOverview();
	void drawSourcesStressTest();

	Path2d		mPath;
	PolyLine2	mPolyline2D;
	PolyLine3	mPolyline3D;
	bool		mPrintFrameRate = false;
};

void ConvenienceDrawingMethodsApp::setup()
{

	mPath.arc( vec2( 0 ), cCircleRadius, 0, M_PI * 1.66f );
	mPath.lineTo( vec2( 0 ) );

	Rand r;
	for( int i = 0; i < 50; ++i ) {
		mPolyline2D.push_back( r.nextVec2() * cCircleRadius );
	}

	// line wrapping around a sphere
	const int numVertices = 48;
	const float azimuth = 12 * M_PI / numVertices;
	// divide total inclination change by particles (from straight down to straight up)
	const float inclination = M_PI / numVertices;
	// fixed radius to generate a sphere
	for( int i = 0; i < numVertices; ++i ) {	// give each particle its starting values
		float x = cCircleRadius * sin( inclination * i ) * cos( azimuth * i );
		float y = cCircleRadius * cos( inclination * i );
		float z = cCircleRadius * sin( inclination * i ) * sin( azimuth * i );
		mPolyline3D.push_back( vec3( x, y, z ) );
	}
}

void ConvenienceDrawingMethodsApp::keyDown( KeyEvent event )
{
#if ! defined( CINDER_GL_ES )
	if( event.getChar() == 'w' )
		gl::setWireframeEnabled( ! gl::isWireframeEnabled() );
#endif
	if( event.getChar() == 'f' )
		mPrintFrameRate = ! mPrintFrameRate;
}

void ConvenienceDrawingMethodsApp::update()
{
	if( mPrintFrameRate && getElapsedFrames() % 30 == 0 )
		console() << "fps: " << getAverageFps()  << endl;
}

void ConvenienceDrawingMethodsApp::draw()
{
	gl::clear( Color( 0.2f, 0.2f, 0.2f ) );

//	drawBasicOverview();
	drawSourcesStressTest();

	CI_CHECK_GL();
}

void ConvenienceDrawingMethodsApp::drawBasicOverview()
{
	gl::setMatricesWindowPersp( getWindowSize() );

	// Draw some rows of circles
	const int numCircles = 4;
	gl::color( Color( 1, 1, 0 ) );
	for( int i = 0; i < numCircles; ++i ) {
		gl::drawSolidCircle( vec2( (i + 1) * cGridStep, cGridStep ), cCircleRadius, i * 3 );
	}

	gl::color( Color( 1, 0, 0 ) );
	for( int i = 0; i < numCircles; ++i ) {
		gl::drawStrokedCircle( vec2( (i + 1) * cGridStep, cGridStep ), cCircleRadius, i * 3 );
	}

	// Draw a line in 2D
	gl::drawLine( vec2( 10, cGridStep * 1.5f ), vec2( getWindowWidth() - 10, cGridStep * 1.5f ) );

	// Draw a Path2d both stroked and filled
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 2 );
		gl::draw( mPath );
		gl::translate( cGridStep, 0 );
		gl::color( Color( 1, 1, 0 ) );
		gl::drawSolid( mPath );
	}

	// Draw a 2D PolyLine both stroked and filled
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 3 );
		gl::color( Color( 1, 0, 0 ) );
		gl::draw( mPolyline2D );
		gl::translate( cGridStep, 0 );
		gl::color( Color( 1, 1, 0 ) );
		gl::drawSolid( mPolyline2D );
	}

	// Draw a 3D PolyLine
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 4 );
		gl::rotate( getElapsedSeconds(), 0, 1, 0 );
		gl::color( Color( 1, 0, 0 ) );
		gl::draw( mPolyline3D );
	}

	// draw a 3D line back into space
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep * 2, cGridStep * 4 );
		gl::rotate( - getElapsedSeconds() * 2, 0, 0.5f, 1 );
		gl::drawLine( vec3( 0, 0, cCircleRadius ), vec3( 0, 0, -cCircleRadius ) );
		gl::drawLine( vec3( -cCircleRadius, 0, 0 ), vec3( cCircleRadius, 0, 0 ) );
		gl::drawLine( vec3( 0, -cCircleRadius, 0 ), vec3( 0, cCircleRadius, 0 ) );
	}

	// draw a geom::Source
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 5 );
		gl::ScopedColor color( Color( 0, 0, 1 ) );

//		auto geom = geom::Rect( Rectf( -cCircleRadius, -cCircleRadius, cCircleRadius, cCircleRadius ) );
		auto geom = geom::Circle().center( vec2( 0 ) ).radius( cCircleRadius );
		gl::draw( geom );
	}

	// draw a 3D geom::Source that uses geom::Attrib::TRIANGLES
	{
		gl::enableDepthRead();

		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep * 2, cGridStep * 5, 2 );
		gl::rotate( M_PI / 2, 0.7f, 0.3f, 0.3f );
		gl::rotate( getElapsedSeconds(), 0, 1, 0 );
		gl::ScopedColor color( Color( 0, 1, 1 ) );

		auto geom = geom::Torus().radius( cCircleRadius, cCircleRadius * 0.7f ).colors();
//		auto geom = geom::Sphere().radius( cCircleRadius ).colors();
		gl::draw( geom );

		gl::disableDepthRead();
	}
}

void ConvenienceDrawingMethodsApp::drawSourcesStressTest()
{
	gl::setMatricesWindowPersp( getWindowSize() );

	const int drawCount = 2000;

	vec2 incr = vec2( getWindowSize() ) / (float)drawCount;
//	auto circleGeom = geom::Circle().center( vec2( 0 ) ).radius( cCircleRadius );
	auto sphereGeom = geom::Sphere().radius( cCircleRadius ).subdivisions( 50 ).colors();
	auto cubeGeom = geom::Cube().subdivisions( 10 ).colors() >> geom::Scale( 10 );

gl::VboMeshRef sphereVboMesh = gl::VboMesh::create( sphereGeom );
gl::VboMeshRef cubeVboMesh = gl::VboMesh::create( cubeGeom );

	gl::ScopedModelMatrix modelScope;

	Timer timer( true );
	for( int i = 0; i < drawCount; i++ ) {
		float perc = (float)i / (float)drawCount;
		gl::translate( incr.x, incr.y );
		gl::ScopedColor color( Color( 0, 0.5f + perc, perc ) );

//		gl::draw( circleGeom );
//		gl::drawSolidCircle( vec2( 0 ), cCircleRadius );

//		gl::drawSphere( vec3(), cCircleRadius, 50 );
		if( i % 2 == 0 )
//			gl::draw( sphereGeom );
			gl::draw( sphereVboMesh );
		else
//			gl::draw( cubeGeom );
			gl::draw( cubeVboMesh );
	}

	if( getElapsedFrames() % 30 == 0 )
		CI_LOG_V( "draw cpu time (ms): " << timer.getSeconds() * 1000 );
}

CINDER_APP( ConvenienceDrawingMethodsApp, RendererGl, []( App::Settings *settings ) {
	settings->setWindowPos( 0, 0 );
	settings->setWindowSize( 960, 564 );
} )
<commit_msg>added some test code for gl::draw( WireGeom )<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/PolyLine.h"
#include "cinder/gl/gl.h"
#include "cinder/gl/VboMesh.h"
#include "cinder/Rand.h"
#include "cinder/Path2d.h"
#include "cinder/Timer.h"
#include "cinder/Log.h"

using namespace ci;
using namespace ci::app;
using namespace std;

const float cCircleRadius = 40;
const float cGridStep = cCircleRadius * 2.2f;

/**
 ConvenienceDrawingMethodsApp:

 Demonstrates most of Cinder's convenience drawing methods.
 These are not the most CPU/GPU-efficient methods of drawing, but they
 are a quick way to get something on screen.
 */
class ConvenienceDrawingMethodsApp : public App {
  public:
	void setup() override;
	void keyDown( KeyEvent event ) override;
	void update() override;
	void draw() override;
  private:
	void drawBasicOverview();
	void drawSourcesStressTest();

	Path2d		mPath;
	PolyLine2	mPolyline2D;
	PolyLine3	mPolyline3D;
	bool		mPrintFrameRate = false;
};

void ConvenienceDrawingMethodsApp::setup()
{

	mPath.arc( vec2( 0 ), cCircleRadius, 0, M_PI * 1.66f );
	mPath.lineTo( vec2( 0 ) );

	Rand r;
	for( int i = 0; i < 50; ++i ) {
		mPolyline2D.push_back( r.nextVec2() * cCircleRadius );
	}

	// line wrapping around a sphere
	const int numVertices = 48;
	const float azimuth = 12 * M_PI / numVertices;
	// divide total inclination change by particles (from straight down to straight up)
	const float inclination = M_PI / numVertices;
	// fixed radius to generate a sphere
	for( int i = 0; i < numVertices; ++i ) {	// give each particle its starting values
		float x = cCircleRadius * sin( inclination * i ) * cos( azimuth * i );
		float y = cCircleRadius * cos( inclination * i );
		float z = cCircleRadius * sin( inclination * i ) * sin( azimuth * i );
		mPolyline3D.push_back( vec3( x, y, z ) );
	}
}

void ConvenienceDrawingMethodsApp::keyDown( KeyEvent event )
{
#if ! defined( CINDER_GL_ES )
	if( event.getChar() == 'w' )
		gl::setWireframeEnabled( ! gl::isWireframeEnabled() );
#endif
	if( event.getChar() == 'f' )
		mPrintFrameRate = ! mPrintFrameRate;
}

void ConvenienceDrawingMethodsApp::update()
{
	if( mPrintFrameRate && getElapsedFrames() % 30 == 0 )
		console() << "fps: " << getAverageFps()  << endl;
}

void ConvenienceDrawingMethodsApp::draw()
{
	gl::clear( Color( 0.2f, 0.2f, 0.2f ) );

	drawBasicOverview();
//	drawSourcesStressTest();

	CI_CHECK_GL();
}

void ConvenienceDrawingMethodsApp::drawBasicOverview()
{
	gl::setMatricesWindowPersp( getWindowSize() );

	// Draw some rows of circles
	const int numCircles = 4;
	gl::color( Color( 1, 1, 0 ) );
	for( int i = 0; i < numCircles; ++i ) {
		gl::drawSolidCircle( vec2( (i + 1) * cGridStep, cGridStep ), cCircleRadius, i * 3 );
	}

	gl::color( Color( 1, 0, 0 ) );
	for( int i = 0; i < numCircles; ++i ) {
		gl::drawStrokedCircle( vec2( (i + 1) * cGridStep, cGridStep ), cCircleRadius, i * 3 );
	}

	// Draw a line in 2D
	gl::drawLine( vec2( 10, cGridStep * 1.5f ), vec2( getWindowWidth() - 10, cGridStep * 1.5f ) );

	// Draw a Path2d both stroked and filled
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 2 );
		gl::draw( mPath );
		gl::translate( cGridStep, 0 );
		gl::color( Color( 1, 1, 0 ) );
		gl::drawSolid( mPath );
	}

	// Draw a 2D PolyLine both stroked and filled
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 3 );
		gl::color( Color( 1, 0, 0 ) );
		gl::draw( mPolyline2D );
		gl::translate( cGridStep, 0 );
		gl::color( Color( 1, 1, 0 ) );
		gl::drawSolid( mPolyline2D );
	}

	// Draw a 3D PolyLine
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 4 );
		gl::rotate( getElapsedSeconds(), 0, 1, 0 );
		gl::color( Color( 1, 0, 0 ) );
		gl::draw( mPolyline3D );
	}

	// draw a 3D line back into space
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep * 2, cGridStep * 4 );
		gl::rotate( - getElapsedSeconds() * 2, 0, 0.5f, 1 );
		gl::drawLine( vec3( 0, 0, cCircleRadius ), vec3( 0, 0, -cCircleRadius ) );
		gl::drawLine( vec3( -cCircleRadius, 0, 0 ), vec3( cCircleRadius, 0, 0 ) );
		gl::drawLine( vec3( 0, -cCircleRadius, 0 ), vec3( 0, cCircleRadius, 0 ) );
	}

	// draw a geom::Source
	{
		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep, cGridStep * 5 );
		gl::ScopedColor color( Color( 0, 0, 1 ) );

//		auto geom = geom::Rect( Rectf( -cCircleRadius, -cCircleRadius, cCircleRadius, cCircleRadius ) );
		auto geom = geom::Circle().center( vec2( 0 ) ).radius( cCircleRadius );
		gl::draw( geom );
	}

	// draw a 3D geom::Source that uses geom::Attrib::TRIANGLES
	{
		gl::ScopedDepth depthScope( true );

		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep * 2, cGridStep * 5, 2 );
		gl::rotate( M_PI / 2, 0.7f, 0.3f, 0.3f );
		gl::rotate( getElapsedSeconds(), 0, 1, 0 );
		gl::ScopedColor color( Color( 0, 1, 1 ) );

		auto geom = geom::Torus().radius( cCircleRadius, cCircleRadius * 0.7f ).colors();
//		auto geom = geom::Sphere().radius( cCircleRadius ).colors();
		gl::draw( geom );
	}

	// draw a 3D geom::Source that uses geom::Attrib::LINES
	{
		gl::ScopedDepth depthScope( true );

		gl::ScopedModelMatrix modelScope;
		gl::translate( cGridStep * 3, cGridStep * 5, 2 );
		gl::rotate( M_PI / 2, 0.7f, 0.3f, 0.3f );
		gl::rotate( getElapsedSeconds(), 0, 1, 0 );
		gl::ScopedColor color( Color( 0, 1, 1 ) );

		auto geom = geom::WireTorus().radius( cCircleRadius, cCircleRadius * 0.7f );
		gl::draw( geom );
	}
}

void ConvenienceDrawingMethodsApp::drawSourcesStressTest()
{
	gl::setMatricesWindowPersp( getWindowSize() );

	const int drawCount = 2000;

	vec2 incr = vec2( getWindowSize() ) / (float)drawCount;
//	auto circleGeom = geom::Circle().center( vec2( 0 ) ).radius( cCircleRadius );
	auto sphereGeom = geom::Sphere().radius( cCircleRadius ).subdivisions( 50 ).colors();
	auto cubeGeom = geom::Cube().subdivisions( 10 ).colors() >> geom::Scale( 10 );

	gl::VboMeshRef sphereVboMesh = gl::VboMesh::create( sphereGeom );
	gl::VboMeshRef cubeVboMesh = gl::VboMesh::create( cubeGeom );

	gl::ScopedModelMatrix modelScope;

	Timer timer( true );
	for( int i = 0; i < drawCount; i++ ) {
		float perc = (float)i / (float)drawCount;
		gl::translate( incr.x, incr.y );
		gl::ScopedColor color( Color( 0, 0.5f + perc, perc ) );

//		gl::draw( circleGeom );
//		gl::drawSolidCircle( vec2( 0 ), cCircleRadius );

//		gl::drawSphere( vec3(), cCircleRadius, 50 );
		if( i % 2 == 0 )
//			gl::draw( sphereGeom );
			gl::draw( sphereVboMesh );
		else
//			gl::draw( cubeGeom );
			gl::draw( cubeVboMesh );
	}

	if( getElapsedFrames() % 30 == 0 )
		CI_LOG_V( "draw cpu time (ms): " << timer.getSeconds() * 1000 );
}

CINDER_APP( ConvenienceDrawingMethodsApp, RendererGl, []( App::Settings *settings ) {
	settings->setWindowPos( 0, 0 );
	settings->setWindowSize( 960, 564 );
} )
<|endoftext|>


<commit_before>#pragma once

#include <memory>
#include <type_traits>

#include "glog/logging.h"

namespace principia {
namespace base {

template<typename Pointer>
class not_null;

// Type traits.
template<typename Pointer>
struct is_not_null : std::false_type {};
template<typename Pointer>
struct is_not_null<not_null<Pointer>> : std::true_type {};

template<typename Pointer>
using _checked_not_null = typename std::enable_if<
    !is_not_null<typename std::remove_reference<Pointer>::type>::value,
    not_null<typename std::remove_reference<Pointer>::type>>::type;

// |not_null<Pointer>| is a wrapper for a non-null object of type |Pointer|.
// |Pointer| should be a C-style pointer or a smart pointer.  |Pointer| must not
// be a const, reference, rvalue reference, or |not_null|.  |not_null<Pointer>|
// is movable and may be left in an invalid state when moved, i.e., its
// |pointer_| may become null.
template<typename Pointer>
class not_null {
 public:
  not_null() = delete;
  not_null(not_null const&) = default;
  // Copy contructor for implicitly convertible pointers.
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null(not_null<OtherPointer> const& other);

  // This constructor may invalidate its argument.
  // NOTE(egg): We would use |= default|, but VS2013 does not implement that for
  // the move constructor;
  not_null(not_null&&);  // NOLINT(build/c++11)
  // Move contructor for implicitly convertible pointers. This constructor may
  // invalidate its argument.
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null(not_null<OtherPointer>&& other);  // NOLINT(build/c++11)
  ~not_null() = default;

  not_null& operator=(not_null const&) = default;
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null& operator=(not_null<OtherPointer> const& other);
  // Implemented as a swap, so the argument remains valid.
  not_null& operator=(not_null&& other);  // NOLINT(build/c++11)
  // This operator may invalidate its argument.
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null& operator=(not_null<OtherPointer>&& other);  // NOLINT(build/c++11)

  // Returns |pointer_|, by const reference to avoid a copy if |Pointer| is
  // |unique_ptr|.
  operator Pointer const&() const;
  // Returns |*pointer|.
  decltype(*Pointer{}) operator*() const;
  decltype(&*Pointer{}) const operator->() const;

  // When |Pointer| has a |get()| member function, this returns
  // |pointer_.get()|.
  template<typename P = Pointer,
           typename = decltype(P{}.get())>
  not_null<decltype(P{}.get())> const get() const;

  // The following operators are redundant for valid |not_null<Pointer>|s with
  // the implicit conversion to |Pointer|, but they should allow some
  // optimization.

  // Returns |false|.
  bool operator==(nullptr_t const other) const;
  // Returns |true|.
  bool operator!=(nullptr_t const other) const;
  // Returns |true|.
  operator bool() const;

 private:
  // Creates a |not_null<Pointer>| whose |pointer_| equals the given |pointer|,
  // dawg.  The constructor does *not* perform a null check.  Callers must
  // perform it if needed before using it.
  explicit not_null(Pointer const& pointer);
  explicit not_null(Pointer&& pointer);  // NOLINT(build/c++11)

  Pointer pointer_;

  template<typename OtherPointer>
  friend class not_null;

  template<typename P>
  friend _checked_not_null<P> check_not_null(P const& pointer);
  template<typename P>
  friend _checked_not_null<P> check_not_null(P&& pointer);  // NOLINT
  template<typename T, typename... Args>
  friend not_null<std::unique_ptr<T>> make_not_null_unique(
      Args&&... args);  // NOLINT(build/c++11)
};

// Use |not_null<Pointer> const| instead.
template<typename Pointer>
class not_null<Pointer const>;

// Use |not_null<Pointer>| instead.
template<typename Pointer>
class not_null<not_null<Pointer>>;

// Use |not_null<Pointer>| instead.
template<typename Pointer>
class not_null<Pointer&>;

// Use |not_null<Pointer>| instead.
template<typename Pointer>
class not_null<Pointer&&>;  // NOLINT(build/c++11)

// Factories taking advantage of template argument deduction.  They call the
// corresponding constructors for |not_null<Pointer>|.

// Returns a |not_null<Pointer>| to |*pointer|.  |CHECK|s that |pointer| is not
// null.
template<typename Pointer>
_checked_not_null<Pointer> check_not_null(Pointer const& pointer);
// Returns a |not_null<Pointer>| to |*pointer|.  |pointer| may be invalid after
// the call.  |CHECK|s that |pointer| is not null.
template<typename Pointer>
_checked_not_null<Pointer> check_not_null(Pointer&& pointer);  // NOLINT

// While the above factories would cover this case using the implicit
// conversion, this results in a redundant |CHECK|.  These functions return
// their argument.

// Returns a copy of |pointer|.
template<typename Pointer>
not_null<Pointer> check_not_null(not_null<Pointer> const& pointer);
// Returns |std::move(pointer)|.  |pointer| may be invalid after the call.
template<typename Pointer>
not_null<Pointer> check_not_null(
    not_null<Pointer>&& pointer);  // NOLINT(build/c++11)

// Factory for a |not_null<std::unique_ptr<T>>|, forwards the arguments to the
// constructor of T.  |make_not_null_unique<T>(args)| is interchangeable with
// |check_not_null(make_unique<T>(args))|, but does not perform a |CHECK|, since
// the result of |make_unique| is not null.
template<typename T, typename... Args>
not_null<std::unique_ptr<T>> make_not_null_unique(
    Args&&... args);  // NOLINT(build/c++11)

// For logging.
template<typename Pointer>
std::ostream& operator<<(std::ostream& stream,
                         not_null<Pointer> const& pointer);

}  // namespace base
}  // namespace principia

#include "base/not_null_body.hpp"
<commit_msg>comments<commit_after>#pragma once

#include <memory>
#include <type_traits>

#include "glog/logging.h"

namespace principia {
namespace base {

template<typename Pointer>
class not_null;

// Type traits.
template<typename Pointer>
struct is_not_null : std::false_type {};
template<typename Pointer>
struct is_not_null<not_null<Pointer>> : std::true_type {};

template<typename Pointer>
using _checked_not_null = typename std::enable_if<
    !is_not_null<typename std::remove_reference<Pointer>::type>::value,
    not_null<typename std::remove_reference<Pointer>::type>>::type;

// |not_null<Pointer>| is a wrapper for a non-null object of type |Pointer|.
// |Pointer| should be a C-style pointer or a smart pointer.  |Pointer| must not
// be a const, reference, rvalue reference, or |not_null|.  |not_null<Pointer>|
// is movable and may be left in an invalid state when moved, i.e., its
// |pointer_| may become null.
template<typename Pointer>
class not_null {
 public:
  not_null() = delete;
  not_null(not_null const&) = default;
  // Copy contructor for implicitly convertible pointers.
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null(not_null<OtherPointer> const& other);

  // This constructor may invalidate its argument.
  // NOTE(egg): We would use |= default|, but VS2013 does not implement that for
  // the move constructor.
  not_null(not_null&&);  // NOLINT(build/c++11)
  // Move contructor for implicitly convertible pointers. This constructor may
  // invalidate its argument.
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null(not_null<OtherPointer>&& other);  // NOLINT(build/c++11)
  ~not_null() = default;

  not_null& operator=(not_null const&) = default;
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null& operator=(not_null<OtherPointer> const& other);
  // Implemented as a swap, so the argument remains valid.
  not_null& operator=(not_null&& other);  // NOLINT(build/c++11)
  // This operator may invalidate its argument.
  template<typename OtherPointer,
           typename = typename std::enable_if<
               std::is_convertible<OtherPointer, Pointer>::value>::type>
  not_null& operator=(not_null<OtherPointer>&& other);  // NOLINT(build/c++11)

  // Returns |pointer_|, by const reference to avoid a copy if |Pointer| is
  // |unique_ptr|.
  operator Pointer const&() const;
  // Returns |*pointer|.
  decltype(*Pointer{}) operator*() const;
  decltype(&*Pointer{}) const operator->() const;

  // When |Pointer| has a |get()| member function, this returns
  // |pointer_.get()|.
  template<typename P = Pointer,
           typename = decltype(P{}.get())>
  not_null<decltype(P{}.get())> const get() const;

  // The following operators are redundant for valid |not_null<Pointer>|s with
  // the implicit conversion to |Pointer|, but they should allow some
  // optimization.

  // Returns |false|.
  bool operator==(nullptr_t const other) const;
  // Returns |true|.
  bool operator!=(nullptr_t const other) const;
  // Returns |true|.
  operator bool() const;

 private:
  // Creates a |not_null<Pointer>| whose |pointer_| equals the given |pointer|,
  // dawg.  The constructor does *not* perform a null check.  Callers must
  // perform one if needed before using it.
  explicit not_null(Pointer const& pointer);
  explicit not_null(Pointer&& pointer);  // NOLINT(build/c++11)

  Pointer pointer_;

  template<typename OtherPointer>
  friend class not_null;

  template<typename P>
  friend _checked_not_null<P> check_not_null(P const& pointer);
  template<typename P>
  friend _checked_not_null<P> check_not_null(P&& pointer);  // NOLINT
  template<typename T, typename... Args>
  friend not_null<std::unique_ptr<T>> make_not_null_unique(
      Args&&... args);  // NOLINT(build/c++11)
};

// Use |not_null<Pointer> const| instead.
template<typename Pointer>
class not_null<Pointer const>;

// Use |not_null<Pointer>| instead.
template<typename Pointer>
class not_null<not_null<Pointer>>;

// Use |not_null<Pointer>| instead.
template<typename Pointer>
class not_null<Pointer&>;

// Use |not_null<Pointer>| instead.
template<typename Pointer>
class not_null<Pointer&&>;  // NOLINT(build/c++11)

// Factories taking advantage of template argument deduction.  They call the
// corresponding constructors for |not_null<Pointer>|.

// Returns a |not_null<Pointer>| to |*pointer|.  |CHECK|s that |pointer| is not
// null.
template<typename Pointer>
_checked_not_null<Pointer> check_not_null(Pointer const& pointer);
// Returns a |not_null<Pointer>| to |*pointer|.  |pointer| may be invalid after
// the call.  |CHECK|s that |pointer| is not null.
template<typename Pointer>
_checked_not_null<Pointer> check_not_null(Pointer&& pointer);  // NOLINT

// While the above factories would cover this case using the implicit
// conversion, this results in a redundant |CHECK|.  These functions return
// their argument.

// Returns a copy of |pointer|.
template<typename Pointer>
not_null<Pointer> check_not_null(not_null<Pointer> const& pointer);
// Returns |std::move(pointer)|.  |pointer| may be invalid after the call.
template<typename Pointer>
not_null<Pointer> check_not_null(
    not_null<Pointer>&& pointer);  // NOLINT(build/c++11)

// Factory for a |not_null<std::unique_ptr<T>>|, forwards the arguments to the
// constructor of T.  |make_not_null_unique<T>(args)| is interchangeable with
// |check_not_null(make_unique<T>(args))|, but does not perform a |CHECK|, since
// the result of |make_unique| is not null.
template<typename T, typename... Args>
not_null<std::unique_ptr<T>> make_not_null_unique(
    Args&&... args);  // NOLINT(build/c++11)

// For logging.
template<typename Pointer>
std::ostream& operator<<(std::ostream& stream,
                         not_null<Pointer> const& pointer);

}  // namespace base
}  // namespace principia

#include "base/not_null_body.hpp"
<|endoftext|>