<commit_before>#include "entity_validator_ui.h"

#include "entity_list.h"
#include "halley/editor_extensions/entity_validator.h"
using namespace Halley;

EntityValidatorUI::EntityValidatorUI(String id, UIFactory& factory)
	: UIWidget(std::move(id), {}, UISizer())
	, factory(factory)
{
	factory.loadUI(*this, "ui/halley/entity_validator");
	setActive(false);
}

void EntityValidatorUI::onMakeUI()
{
	getWidgetAs<UIImage>("capsule")->addBehaviour(std::make_shared<UIPulseSpriteBehaviour>(Colour4f(1, 0, 0), 2.0, 1.0));
}

void EntityValidatorUI::setValidator(EntityValidator& v)
{
	validator = &v;
	refresh();
}

void EntityValidatorUI::setEntity(EntityData& e, IEntityEditor& editor, Resources& resources)
{
	curEntity = &e;
	entityEditor = &editor;
	gameResources = &resources;

	isPrefab = !curEntity->getPrefab().isEmpty() && gameResources->exists<Prefab>(curEntity->getPrefab());
	if (isPrefab) {
		const auto prefab = gameResources->get<Prefab>(curEntity->getPrefab());
		curEntityInstance = prefab->getEntityData().instantiateWithAsCopy(*curEntity);
	}

	refresh();
}

void EntityValidatorUI::refresh()
{
	if (!curEntity || !validator) {
		return;
	}

	std::vector<IEntityValidator::Result> result;
	if (isPrefab) {
		result = validator->validateEntity(curEntityInstance, true);
	} else {
		result = validator->validateEntity(*curEntity, false);
	}

	if (result != curResultSet) {
		curResultSet = std::move(result);
		setActive(!curResultSet.empty());

		auto parent = getWidget("validationFields");
		parent->clear();

		bool first = true;

		for (const auto& curResult: curResultSet) {
			if (!first) {
				auto col = factory.getColourScheme()->getColour("taskError");
				parent->add(std::make_shared<UIImage>(Sprite().setImage(factory.getResources(), "halley_ui/ui_separator.png").setColour(col)), 0, Vector4f(0, 4, 0, 4));
			}
			first = false;

			auto label = std::make_shared<UILabel>("", factory.getStyle("labelLight"), curResult.errorMessage);
			label->setMaxWidth(300.0f);
			parent->add(label);

			for (const auto& action: curResult.suggestedActions) {
				if (validator->canApplyAction(*entityEditor, *curEntity, action.actionData)) {
					auto button = std::make_shared<UIButton>("action", factory.getStyle("buttonThin"), action.label);
					button->setHandle(UIEventType::ButtonClicked, [this, actionData = ConfigNode(action.actionData)] (const UIEvent& event)
					{
						Concurrent::execute(Executors::getMainThread(), [=] () {
							validator->applyAction(*entityEditor, *curEntity, actionData);
							entityEditor->reloadEntity();
						});
					});
					parent->add(button);
				}
			}
		}
	}
}

EntityValidatorListUI::EntityValidatorListUI(String id, UIFactory& factory)
	: UIWidget(std::move(id), {}, UISizer())
	, factory(factory)
{
	factory.loadUI(*this, "ui/halley/entity_validator_list");
	setActive(false);
}

void EntityValidatorListUI::onMakeUI()
{
	setHandle(UIEventType::ButtonClicked, "prev", [=] (const UIEvent& event)
	{
		move(-1);
	});

	setHandle(UIEventType::ButtonClicked, "next", [=] (const UIEvent& event)
	{
		move(1);
	});

	getWidgetAs<UIImage>("capsule")->addBehaviour(std::make_shared<UIPulseSpriteBehaviour>(Colour4f(1, 0, 0), 2.0, 1.0));
	description = getWidgetAs<UILabel>("description");
}

void EntityValidatorListUI::update(Time t, bool moved)
{
	const auto entityListStrong = entityList.lock();
	if (entityListStrong) {
		const auto& list = entityListStrong->getList();
		const auto curSel = list.getSelectedOption();
		const auto iter = std::find(invalidEntities.begin(), invalidEntities.end(), curSel);
		const int curPos = iter != invalidEntities.end() ? static_cast<int>(iter - invalidEntities.begin() + 1) : 0;
		description->setText(LocalisedString::fromHardcodedString("Entities have validation errors [" + (curPos > 0 ? toString(curPos) : "-") + "/" + toString(invalidEntities.size()) + "]"));
	}
}

void EntityValidatorListUI::setList(std::weak_ptr<EntityList> list)
{
	entityList = list;
}

void EntityValidatorListUI::setInvalidEntities(std::vector<int> entities)
{
	invalidEntities = std::move(entities);
	setActive(!invalidEntities.empty());
}

void EntityValidatorListUI::move(int delta)
{
	auto& list = entityList.lock()->getList();
	const auto curSel = list.getSelectedOption();
	int newSel = curSel;

	if (delta == 1) {
		newSel = invalidEntities.front();
		for (int e: invalidEntities) {
			if (e > curSel) {
				newSel = e;
				break;
			}
		}
	} else if (delta == -1) {
		newSel = invalidEntities.back();
		for (int i = int(invalidEntities.size()); --i >= 0;) {
			int e = invalidEntities[i];
			if (e < curSel) {
				newSel = e;
				break;
			}
		}
	}

	if (newSel != curSel) {
		list.setSelectedOption(newSel);
	}
}
<commit_msg>Tweak colour<commit_after>#include "entity_validator_ui.h"

#include "entity_list.h"
#include "halley/editor_extensions/entity_validator.h"
using namespace Halley;

EntityValidatorUI::EntityValidatorUI(String id, UIFactory& factory)
	: UIWidget(std::move(id), {}, UISizer())
	, factory(factory)
{
	factory.loadUI(*this, "ui/halley/entity_validator");
	setActive(false);
}

void EntityValidatorUI::onMakeUI()
{
	getWidgetAs<UIImage>("capsule")->addBehaviour(std::make_shared<UIPulseSpriteBehaviour>(Colour4f(1, 0, 0), 2.0, 1.0));
}

void EntityValidatorUI::setValidator(EntityValidator& v)
{
	validator = &v;
	refresh();
}

void EntityValidatorUI::setEntity(EntityData& e, IEntityEditor& editor, Resources& resources)
{
	curEntity = &e;
	entityEditor = &editor;
	gameResources = &resources;

	isPrefab = !curEntity->getPrefab().isEmpty() && gameResources->exists<Prefab>(curEntity->getPrefab());
	if (isPrefab) {
		const auto prefab = gameResources->get<Prefab>(curEntity->getPrefab());
		curEntityInstance = prefab->getEntityData().instantiateWithAsCopy(*curEntity);
	}

	refresh();
}

void EntityValidatorUI::refresh()
{
	if (!curEntity || !validator) {
		return;
	}

	std::vector<IEntityValidator::Result> result;
	if (isPrefab) {
		result = validator->validateEntity(curEntityInstance, true);
	} else {
		result = validator->validateEntity(*curEntity, false);
	}

	if (result != curResultSet) {
		curResultSet = std::move(result);
		setActive(!curResultSet.empty());

		auto parent = getWidget("validationFields");
		parent->clear();

		bool first = true;

		for (const auto& curResult: curResultSet) {
			if (!first) {
				auto col = factory.getColourScheme()->getColour("ui_text");
				parent->add(std::make_shared<UIImage>(Sprite().setImage(factory.getResources(), "halley_ui/ui_separator.png").setColour(col)), 0, Vector4f(0, 4, 0, 4));
			}
			first = false;

			auto label = std::make_shared<UILabel>("", factory.getStyle("labelLight"), curResult.errorMessage);
			label->setMaxWidth(300.0f);
			parent->add(label);

			for (const auto& action: curResult.suggestedActions) {
				if (validator->canApplyAction(*entityEditor, *curEntity, action.actionData)) {
					auto button = std::make_shared<UIButton>("action", factory.getStyle("buttonThin"), action.label);
					button->setHandle(UIEventType::ButtonClicked, [this, actionData = ConfigNode(action.actionData)] (const UIEvent& event)
					{
						Concurrent::execute(Executors::getMainThread(), [=] () {
							validator->applyAction(*entityEditor, *curEntity, actionData);
							entityEditor->reloadEntity();
						});
					});
					parent->add(button);
				}
			}
		}
	}
}

EntityValidatorListUI::EntityValidatorListUI(String id, UIFactory& factory)
	: UIWidget(std::move(id), {}, UISizer())
	, factory(factory)
{
	factory.loadUI(*this, "ui/halley/entity_validator_list");
	setActive(false);
}

void EntityValidatorListUI::onMakeUI()
{
	setHandle(UIEventType::ButtonClicked, "prev", [=] (const UIEvent& event)
	{
		move(-1);
	});

	setHandle(UIEventType::ButtonClicked, "next", [=] (const UIEvent& event)
	{
		move(1);
	});

	getWidgetAs<UIImage>("capsule")->addBehaviour(std::make_shared<UIPulseSpriteBehaviour>(Colour4f(1, 0, 0), 2.0, 1.0));
	description = getWidgetAs<UILabel>("description");
}

void EntityValidatorListUI::update(Time t, bool moved)
{
	const auto entityListStrong = entityList.lock();
	if (entityListStrong) {
		const auto& list = entityListStrong->getList();
		const auto curSel = list.getSelectedOption();
		const auto iter = std::find(invalidEntities.begin(), invalidEntities.end(), curSel);
		const int curPos = iter != invalidEntities.end() ? static_cast<int>(iter - invalidEntities.begin() + 1) : 0;
		description->setText(LocalisedString::fromHardcodedString("Entities have validation errors [" + (curPos > 0 ? toString(curPos) : "-") + "/" + toString(invalidEntities.size()) + "]"));
	}
}

void EntityValidatorListUI::setList(std::weak_ptr<EntityList> list)
{
	entityList = list;
}

void EntityValidatorListUI::setInvalidEntities(std::vector<int> entities)
{
	invalidEntities = std::move(entities);
	setActive(!invalidEntities.empty());
}

void EntityValidatorListUI::move(int delta)
{
	auto& list = entityList.lock()->getList();
	const auto curSel = list.getSelectedOption();
	int newSel = curSel;

	if (delta == 1) {
		newSel = invalidEntities.front();
		for (int e: invalidEntities) {
			if (e > curSel) {
				newSel = e;
				break;
			}
		}
	} else if (delta == -1) {
		newSel = invalidEntities.back();
		for (int i = int(invalidEntities.size()); --i >= 0;) {
			int e = invalidEntities[i];
			if (e < curSel) {
				newSel = e;
				break;
			}
		}
	}

	if (newSel != curSel) {
		list.setSelectedOption(newSel);
	}
}
<|endoftext|>


<commit_before>/*
Copyright libCellML Contributors

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

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

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

#include "libcellml/component.h"
#include "libcellml/importsource.h"
#include "libcellml/model.h"
#include "libcellml/parser.h"
#include "libcellml/variable.h"
#include "libcellml/units.h"

#include <algorithm>
#include <fstream>
#include <map>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>

namespace libcellml {

/**
 * @brief The Model::ModelImpl struct.
 *
 * This struct is the private implementation struct for the Model class.  Separating
 * the implementation from the definition allows for greater flexibility when
 * distributing the code.
 */
struct Model::ModelImpl
{
    std::vector<UnitsPtr>::iterator findUnits(const std::string &name);
    std::vector<UnitsPtr>::iterator findUnits(const UnitsPtr &units);
    std::vector<UnitsPtr> mUnits;
};

std::vector<UnitsPtr>::iterator Model::ModelImpl::findUnits(const std::string &name)
{
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u->getName() == name; });
}

std::vector<UnitsPtr>::iterator Model::ModelImpl::findUnits(const UnitsPtr &units)
{
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u == units; });
}

Model::Model()
#ifndef SWIG
    : std::enable_shared_from_this<Model>()
    , mPimpl(new ModelImpl())
#else
    : mPimpl(new ModelImpl())
#endif
{
}

Model::~Model()
{
    delete mPimpl;
}

Model::Model(const Model &rhs)
    : ComponentEntity(rhs)
#ifndef SWIG
    , std::enable_shared_from_this<Model>()
#endif
    , mPimpl(new ModelImpl())
{
    mPimpl->mUnits = rhs.mPimpl->mUnits;
}

Model::Model(Model &&rhs) noexcept
    : ComponentEntity(std::move(rhs))
#ifndef SWIG
    , std::enable_shared_from_this<Model>()
#endif
    ,mPimpl(rhs.mPimpl)
{
    rhs.mPimpl = nullptr;
}

Model& Model::operator=(Model rhs)
{
    ComponentEntity::operator= (rhs);
    rhs.swap(*this);
    return *this;
}

void Model::swap(Model &rhs)
{
    std::swap(this->mPimpl, rhs.mPimpl);
}

void Model::doAddComponent(const ComponentPtr &component)
{
    // Check for cycles.
    if (!hasParent(component.get())) {
        component->setParent(this);
        ComponentEntity::doAddComponent(component);
    }
}

void Model::addUnits(const UnitsPtr &units)
{
    mPimpl->mUnits.push_back(units);
}

bool Model::removeUnits(size_t index)
{
    bool status = false;
    if (index < mPimpl->mUnits.size()) {
        mPimpl->mUnits.erase(mPimpl->mUnits.begin() + index);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const std::string &name)
{
    bool status = false;
    auto result = mPimpl->findUnits(name);
    if (result != mPimpl->mUnits.end()) {
        mPimpl->mUnits.erase(result);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const UnitsPtr &units)
{
    bool status = false;
    auto result = mPimpl->findUnits(units);
    if (result != mPimpl->mUnits.end()) {
        mPimpl->mUnits.erase(result);
        status = true;
    }

    return status;
}

void Model::removeAllUnits()
{
    mPimpl->mUnits.clear();
}

bool Model::hasUnits(const std::string &name) const
{
    return mPimpl->findUnits(name) != mPimpl->mUnits.end();
}

bool Model::hasUnits(const UnitsPtr &units) const
{
    return mPimpl->findUnits(units) != mPimpl->mUnits.end();
}

UnitsPtr Model::getUnits(size_t index) const
{
    UnitsPtr units = nullptr;
    if (index < mPimpl->mUnits.size()) {
        units = mPimpl->mUnits.at(index);
    }

    return units;
}

UnitsPtr Model::getUnits(const std::string &name) const
{
    UnitsPtr units = nullptr;
    auto result = mPimpl->findUnits(name);
    if (result != mPimpl->mUnits.end()) {
        units = *result;
    }

    return units;
}

UnitsPtr Model::takeUnits(size_t index)
{
    UnitsPtr units = nullptr;
    if (index < mPimpl->mUnits.size()) {
        units = mPimpl->mUnits.at(index);
        removeUnits(index);
        units->clearParent();
    }

    return units;
}

UnitsPtr Model::takeUnits(const std::string &name)
{
    return takeUnits(mPimpl->findUnits(name) - mPimpl->mUnits.begin());
}

bool Model::replaceUnits(size_t index, const UnitsPtr &units)
{
    bool status = false;
    if (removeUnits(index)) {
        mPimpl->mUnits.insert(mPimpl->mUnits.begin() + index, units);
        status = true;
    }

    return status;
}

bool Model::replaceUnits(const std::string &name, const UnitsPtr &units)
{
    return replaceUnits(mPimpl->findUnits(name) - mPimpl->mUnits.begin(), units);
}

bool Model::replaceUnits(const UnitsPtr &oldUnits, const UnitsPtr &newUnits)
{
    return replaceUnits(mPimpl->findUnits(oldUnits) - mPimpl->mUnits.begin(), newUnits);
}

size_t Model::unitsCount() const
{
    return mPimpl->mUnits.size();
}

/**
 * @brief Resolve the path of the given filename using the given base.
 *
 * Resolves the full path to the given @p filename using the @p base.
 *
 * This function is only intended to work with local files.  It may not
 * work with bases that use the 'file://' prefix.
 *
 * @param filename The @c std::string relative path from the base path.
 * @param base The @c std::string location on local disk for determining the full path from.
 * @return The full path from the @p base location to the @p filename
 */
std::string resolvePath(const std::string &filename, const std::string &base)
{
    // We can be naive here as we know what we are dealing with
    std::string path = base.substr(0, base.find_last_of('/')+1) + filename;
    return path;
}

void resolveImport(const ImportedEntityPtr &importedEntity,
                   const std::string &baseFile)
{
    if (importedEntity->isImport()) {
        ImportSourcePtr importSource = importedEntity->getImportSource();
        if (!importSource->hasModel()) {
            std::string url = resolvePath(importSource->getUrl(), baseFile);
            std::ifstream file(url);
            if (file.good()) {
                std::stringstream buffer;
                buffer << file.rdbuf();
                Parser parser;
                ModelPtr model = parser.parseModel(buffer.str());
                importSource->setModel(model);
                model->resolveImports(url);
            }
        }
    }
}

void resolveComponentImports(const ComponentEntityPtr &parentComponentEntity,
                             const std::string &baseFile)
{
    for (size_t n = 0; n < parentComponentEntity->componentCount(); ++n)
    {
        ComponentPtr component = parentComponentEntity->getComponent(n);
        if (component->isImport()) {
            resolveImport(component, baseFile);
        } else {
            resolveComponentImports(component, baseFile);
        }
    }
}

void Model::resolveImports(const std::string &baseFile)
{
    for (size_t n = 0; n < unitsCount(); ++n)
    {
        UnitsPtr units = getUnits(n);
        resolveImport(units, baseFile);
    }
    resolveComponentImports(shared_from_this(), baseFile);
}

bool isUnresolvedImport(const ImportedEntityPtr &importedEntity)
{
    bool unresolvedImport = false;
    if (importedEntity->isImport()) {
        ImportSourcePtr importedSource = importedEntity->getImportSource();
        if (!importedSource->hasModel()) {
            unresolvedImport = true;
        }
    }
    return unresolvedImport;
}

bool hasUnresolvedComponentImports(const ComponentEntityPtr &parentComponentEntity);

bool doHasUnresolvedComponentImports(const ComponentPtr &component)
{
    bool unresolvedImports = false;
    if (component->isImport()) {
        unresolvedImports = isUnresolvedImport(component);
        if (!unresolvedImports) {
            // Check that the imported component can import all it needs from its model.
            ImportSourcePtr importedSource = component->getImportSource();
            if (importedSource->hasModel()) {
                ModelPtr importedModel = importedSource->getModel();
                ComponentPtr importedComponent = importedModel->getComponent(component->getImportReference());
                unresolvedImports = doHasUnresolvedComponentImports(importedComponent);
            }
        }
    } else {
        unresolvedImports = hasUnresolvedComponentImports(component);
    }
    return unresolvedImports;
}

bool hasUnresolvedComponentImports(const ComponentEntityPtr &parentComponentEntity)
{
    bool unresolvedImports = false;
    for (size_t n = 0; n < parentComponentEntity->componentCount() && !unresolvedImports; ++n)
    {
        ComponentPtr component = parentComponentEntity->getComponent(n);
        unresolvedImports = doHasUnresolvedComponentImports(component);
    }
    return unresolvedImports;
}

bool Model::hasUnresolvedImports()
{
    bool unresolvedImports = false;
    for (size_t n = 0; n < unitsCount() && !unresolvedImports; ++n)
    {
        UnitsPtr units = getUnits(n);
        unresolvedImports = isUnresolvedImport(units);
    }
    if (!unresolvedImports) {
        unresolvedImports = hasUnresolvedComponentImports(shared_from_this());
    }
    return unresolvedImports;
}

}
<commit_msg>Make Clang-Tidy happy.<commit_after>/*
Copyright libCellML Contributors

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

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

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

#include "libcellml/component.h"
#include "libcellml/importsource.h"
#include "libcellml/model.h"
#include "libcellml/parser.h"
#include "libcellml/variable.h"
#include "libcellml/units.h"

#include <algorithm>
#include <fstream>
#include <map>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>

namespace libcellml {

/**
 * @brief The Model::ModelImpl struct.
 *
 * This struct is the private implementation struct for the Model class.  Separating
 * the implementation from the definition allows for greater flexibility when
 * distributing the code.
 */
struct Model::ModelImpl
{
    std::vector<UnitsPtr>::iterator findUnits(const std::string &name);
    std::vector<UnitsPtr>::iterator findUnits(const UnitsPtr &units);
    std::vector<UnitsPtr> mUnits;
};

std::vector<UnitsPtr>::iterator Model::ModelImpl::findUnits(const std::string &name)
{
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u->getName() == name; });
}

std::vector<UnitsPtr>::iterator Model::ModelImpl::findUnits(const UnitsPtr &units)
{
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u == units; });
}

Model::Model()
    : mPimpl(new ModelImpl())
{
}

Model::~Model()
{
    delete mPimpl;
}

Model::Model(const Model &rhs)
    : ComponentEntity(rhs)
#ifndef SWIG
    , std::enable_shared_from_this<Model>(rhs)
#endif
    , mPimpl(new ModelImpl())
{
    mPimpl->mUnits = rhs.mPimpl->mUnits;
}

Model::Model(Model &&rhs) noexcept
    : ComponentEntity(std::move(rhs))
    , mPimpl(rhs.mPimpl)
{
    rhs.mPimpl = nullptr;
}

Model& Model::operator=(Model rhs)
{
    ComponentEntity::operator= (rhs);
    rhs.swap(*this);
    return *this;
}

void Model::swap(Model &rhs)
{
    std::swap(this->mPimpl, rhs.mPimpl);
}

void Model::doAddComponent(const ComponentPtr &component)
{
    // Check for cycles.
    if (!hasParent(component.get())) {
        component->setParent(this);
        ComponentEntity::doAddComponent(component);
    }
}

void Model::addUnits(const UnitsPtr &units)
{
    mPimpl->mUnits.push_back(units);
}

bool Model::removeUnits(size_t index)
{
    bool status = false;
    if (index < mPimpl->mUnits.size()) {
        mPimpl->mUnits.erase(mPimpl->mUnits.begin() + index);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const std::string &name)
{
    bool status = false;
    auto result = mPimpl->findUnits(name);
    if (result != mPimpl->mUnits.end()) {
        mPimpl->mUnits.erase(result);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const UnitsPtr &units)
{
    bool status = false;
    auto result = mPimpl->findUnits(units);
    if (result != mPimpl->mUnits.end()) {
        mPimpl->mUnits.erase(result);
        status = true;
    }

    return status;
}

void Model::removeAllUnits()
{
    mPimpl->mUnits.clear();
}

bool Model::hasUnits(const std::string &name) const
{
    return mPimpl->findUnits(name) != mPimpl->mUnits.end();
}

bool Model::hasUnits(const UnitsPtr &units) const
{
    return mPimpl->findUnits(units) != mPimpl->mUnits.end();
}

UnitsPtr Model::getUnits(size_t index) const
{
    UnitsPtr units = nullptr;
    if (index < mPimpl->mUnits.size()) {
        units = mPimpl->mUnits.at(index);
    }

    return units;
}

UnitsPtr Model::getUnits(const std::string &name) const
{
    UnitsPtr units = nullptr;
    auto result = mPimpl->findUnits(name);
    if (result != mPimpl->mUnits.end()) {
        units = *result;
    }

    return units;
}

UnitsPtr Model::takeUnits(size_t index)
{
    UnitsPtr units = nullptr;
    if (index < mPimpl->mUnits.size()) {
        units = mPimpl->mUnits.at(index);
        removeUnits(index);
        units->clearParent();
    }

    return units;
}

UnitsPtr Model::takeUnits(const std::string &name)
{
    return takeUnits(mPimpl->findUnits(name) - mPimpl->mUnits.begin());
}

bool Model::replaceUnits(size_t index, const UnitsPtr &units)
{
    bool status = false;
    if (removeUnits(index)) {
        mPimpl->mUnits.insert(mPimpl->mUnits.begin() + index, units);
        status = true;
    }

    return status;
}

bool Model::replaceUnits(const std::string &name, const UnitsPtr &units)
{
    return replaceUnits(mPimpl->findUnits(name) - mPimpl->mUnits.begin(), units);
}

bool Model::replaceUnits(const UnitsPtr &oldUnits, const UnitsPtr &newUnits)
{
    return replaceUnits(mPimpl->findUnits(oldUnits) - mPimpl->mUnits.begin(), newUnits);
}

size_t Model::unitsCount() const
{
    return mPimpl->mUnits.size();
}

/**
 * @brief Resolve the path of the given filename using the given base.
 *
 * Resolves the full path to the given @p filename using the @p base.
 *
 * This function is only intended to work with local files.  It may not
 * work with bases that use the 'file://' prefix.
 *
 * @param filename The @c std::string relative path from the base path.
 * @param base The @c std::string location on local disk for determining the full path from.
 * @return The full path from the @p base location to the @p filename
 */
std::string resolvePath(const std::string &filename, const std::string &base)
{
    // We can be naive here as we know what we are dealing with
    std::string path = base.substr(0, base.find_last_of('/')+1) + filename;
    return path;
}

void resolveImport(const ImportedEntityPtr &importedEntity,
                   const std::string &baseFile)
{
    if (importedEntity->isImport()) {
        ImportSourcePtr importSource = importedEntity->getImportSource();
        if (!importSource->hasModel()) {
            std::string url = resolvePath(importSource->getUrl(), baseFile);
            std::ifstream file(url);
            if (file.good()) {
                std::stringstream buffer;
                buffer << file.rdbuf();
                Parser parser;
                ModelPtr model = parser.parseModel(buffer.str());
                importSource->setModel(model);
                model->resolveImports(url);
            }
        }
    }
}

void resolveComponentImports(const ComponentEntityPtr &parentComponentEntity,
                             const std::string &baseFile)
{
    for (size_t n = 0; n < parentComponentEntity->componentCount(); ++n)
    {
        ComponentPtr component = parentComponentEntity->getComponent(n);
        if (component->isImport()) {
            resolveImport(component, baseFile);
        } else {
            resolveComponentImports(component, baseFile);
        }
    }
}

void Model::resolveImports(const std::string &baseFile)
{
    for (size_t n = 0; n < unitsCount(); ++n)
    {
        UnitsPtr units = getUnits(n);
        resolveImport(units, baseFile);
    }
    resolveComponentImports(shared_from_this(), baseFile);
}

bool isUnresolvedImport(const ImportedEntityPtr &importedEntity)
{
    bool unresolvedImport = false;
    if (importedEntity->isImport()) {
        ImportSourcePtr importedSource = importedEntity->getImportSource();
        if (!importedSource->hasModel()) {
            unresolvedImport = true;
        }
    }
    return unresolvedImport;
}

bool hasUnresolvedComponentImports(const ComponentEntityPtr &parentComponentEntity);

bool doHasUnresolvedComponentImports(const ComponentPtr &component)
{
    bool unresolvedImports = false;
    if (component->isImport()) {
        unresolvedImports = isUnresolvedImport(component);
        if (!unresolvedImports) {
            // Check that the imported component can import all it needs from its model.
            ImportSourcePtr importedSource = component->getImportSource();
            if (importedSource->hasModel()) {
                ModelPtr importedModel = importedSource->getModel();
                ComponentPtr importedComponent = importedModel->getComponent(component->getImportReference());
                unresolvedImports = doHasUnresolvedComponentImports(importedComponent);
            }
        }
    } else {
        unresolvedImports = hasUnresolvedComponentImports(component);
    }
    return unresolvedImports;
}

bool hasUnresolvedComponentImports(const ComponentEntityPtr &parentComponentEntity)
{
    bool unresolvedImports = false;
    for (size_t n = 0; n < parentComponentEntity->componentCount() && !unresolvedImports; ++n)
    {
        ComponentPtr component = parentComponentEntity->getComponent(n);
        unresolvedImports = doHasUnresolvedComponentImports(component);
    }
    return unresolvedImports;
}

bool Model::hasUnresolvedImports()
{
    bool unresolvedImports = false;
    for (size_t n = 0; n < unitsCount() && !unresolvedImports; ++n)
    {
        UnitsPtr units = getUnits(n);
        unresolvedImports = isUnresolvedImport(units);
    }
    if (!unresolvedImports) {
        unresolvedImports = hasUnresolvedComponentImports(shared_from_this());
    }
    return unresolvedImports;
}

}
<|endoftext|>


<commit_before>#include "command.hh"
#include "store-api.hh"
#include "fs-accessor.hh"
#include "nar-accessor.hh"
#include "common-args.hh"
#include "json.hh"

using namespace nix;

struct MixLs : virtual Args, MixJSON
{
    std::string path;

    bool recursive = false;
    bool verbose = false;
    bool showDirectory = false;

    MixLs()
    {
        mkFlag('R', "recursive", "list subdirectories recursively", &recursive);
        mkFlag('l', "long", "show more file information", &verbose);
        mkFlag('d', "directory", "show directories rather than their contents", &showDirectory);
    }

    void listText(ref<FSAccessor> accessor)
    {
        std::function<void(const FSAccessor::Stat &, const Path &, const std::string &, bool)> doPath;

        auto showFile = [&](const Path & curPath, const std::string & relPath) {
            if (verbose) {
                auto st = accessor->stat(curPath);
                std::string tp =
                    st.type == FSAccessor::Type::tRegular ?
                        (st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") :
                    st.type == FSAccessor::Type::tSymlink ? "lrwxrwxrwx" :
                    "dr-xr-xr-x";
                std::cout <<
                    (format("%s %20d %s") % tp % st.fileSize % relPath);
                if (st.type == FSAccessor::Type::tSymlink)
                    std::cout << " -> " << accessor->readLink(curPath)
                    ;
                std::cout << "\n";
                if (recursive && st.type == FSAccessor::Type::tDirectory)
                    doPath(st, curPath, relPath, false);
            } else {
                std::cout << relPath << "\n";
                if (recursive) {
                    auto st = accessor->stat(curPath);
                    if (st.type == FSAccessor::Type::tDirectory)
                        doPath(st, curPath, relPath, false);
                }
            }
        };

        doPath = [&](const FSAccessor::Stat & st, const Path & curPath,
            const std::string & relPath, bool showDirectory)
        {
            if (st.type == FSAccessor::Type::tDirectory && !showDirectory) {
                auto names = accessor->readDirectory(curPath);
                for (auto & name : names)
                    showFile(curPath + "/" + name, relPath + "/" + name);
            } else
                showFile(curPath, relPath);
        };

        auto st = accessor->stat(path);
        if (st.type == FSAccessor::Type::tMissing)
            throw Error(format("path '%1%' does not exist") % path);
        doPath(st, path,
            st.type == FSAccessor::Type::tDirectory ? "." : baseNameOf(path),
            showDirectory);
    }

    void list(ref<FSAccessor> accessor)
    {
        if (path == "/") path = "";

        if (json) {
            JSONPlaceholder jsonRoot(std::cout);
            listNar(jsonRoot, accessor, path, recursive);
        } else
            listText(accessor);
    }
};

struct CmdLsStore : StoreCommand, MixLs
{
    CmdLsStore()
    {
        expectArg("path", &path);
    }

    Examples examples() override
    {
        return {
            Example{
                "To list the contents of a store path in a binary cache:",
                "nix ls-store --store https://cache.nixos.org/ -lR /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10"
            },
        };
    }

    std::string name() override
    {
        return "ls-store";
    }

    std::string description() override
    {
        return "show information about a store path";
    }

    void run(ref<Store> store) override
    {
        list(store->getFSAccessor());
    }
};

struct CmdLsNar : Command, MixLs
{
    Path narPath;

    CmdLsNar()
    {
        expectArg("nar", &narPath);
        expectArg("path", &path);
    }

    Examples examples() override
    {
        return {
            Example{
                "To list a specific file in a NAR:",
                "nix ls-nar -l hello.nar /bin/hello"
            },
        };
    }

    std::string name() override
    {
        return "ls-nar";
    }

    std::string description() override
    {
        return "show information about the contents of a NAR file";
    }

    void run() override
    {
        list(makeNarAccessor(make_ref<std::string>(readFile(narPath))));
    }
};

static RegisterCommand r1(make_ref<CmdLsStore>());
static RegisterCommand r2(make_ref<CmdLsNar>());
<commit_msg>nix ls-nar: allow reading from FIFOs<commit_after>#include "command.hh"
#include "store-api.hh"
#include "fs-accessor.hh"
#include "nar-accessor.hh"
#include "common-args.hh"
#include "json.hh"

using namespace nix;

struct MixLs : virtual Args, MixJSON
{
    std::string path;

    bool recursive = false;
    bool verbose = false;
    bool showDirectory = false;

    MixLs()
    {
        mkFlag('R', "recursive", "list subdirectories recursively", &recursive);
        mkFlag('l', "long", "show more file information", &verbose);
        mkFlag('d', "directory", "show directories rather than their contents", &showDirectory);
    }

    void listText(ref<FSAccessor> accessor)
    {
        std::function<void(const FSAccessor::Stat &, const Path &, const std::string &, bool)> doPath;

        auto showFile = [&](const Path & curPath, const std::string & relPath) {
            if (verbose) {
                auto st = accessor->stat(curPath);
                std::string tp =
                    st.type == FSAccessor::Type::tRegular ?
                        (st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") :
                    st.type == FSAccessor::Type::tSymlink ? "lrwxrwxrwx" :
                    "dr-xr-xr-x";
                std::cout <<
                    (format("%s %20d %s") % tp % st.fileSize % relPath);
                if (st.type == FSAccessor::Type::tSymlink)
                    std::cout << " -> " << accessor->readLink(curPath)
                    ;
                std::cout << "\n";
                if (recursive && st.type == FSAccessor::Type::tDirectory)
                    doPath(st, curPath, relPath, false);
            } else {
                std::cout << relPath << "\n";
                if (recursive) {
                    auto st = accessor->stat(curPath);
                    if (st.type == FSAccessor::Type::tDirectory)
                        doPath(st, curPath, relPath, false);
                }
            }
        };

        doPath = [&](const FSAccessor::Stat & st, const Path & curPath,
            const std::string & relPath, bool showDirectory)
        {
            if (st.type == FSAccessor::Type::tDirectory && !showDirectory) {
                auto names = accessor->readDirectory(curPath);
                for (auto & name : names)
                    showFile(curPath + "/" + name, relPath + "/" + name);
            } else
                showFile(curPath, relPath);
        };

        auto st = accessor->stat(path);
        if (st.type == FSAccessor::Type::tMissing)
            throw Error(format("path '%1%' does not exist") % path);
        doPath(st, path,
            st.type == FSAccessor::Type::tDirectory ? "." : baseNameOf(path),
            showDirectory);
    }

    void list(ref<FSAccessor> accessor)
    {
        if (path == "/") path = "";

        if (json) {
            JSONPlaceholder jsonRoot(std::cout);
            listNar(jsonRoot, accessor, path, recursive);
        } else
            listText(accessor);
    }
};

struct CmdLsStore : StoreCommand, MixLs
{
    CmdLsStore()
    {
        expectArg("path", &path);
    }

    Examples examples() override
    {
        return {
            Example{
                "To list the contents of a store path in a binary cache:",
                "nix ls-store --store https://cache.nixos.org/ -lR /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10"
            },
        };
    }

    std::string name() override
    {
        return "ls-store";
    }

    std::string description() override
    {
        return "show information about a store path";
    }

    void run(ref<Store> store) override
    {
        list(store->getFSAccessor());
    }
};

struct CmdLsNar : Command, MixLs
{
    Path narPath;

    CmdLsNar()
    {
        expectArg("nar", &narPath);
        expectArg("path", &path);
    }

    Examples examples() override
    {
        return {
            Example{
                "To list a specific file in a NAR:",
                "nix ls-nar -l hello.nar /bin/hello"
            },
        };
    }

    std::string name() override
    {
        return "ls-nar";
    }

    std::string description() override
    {
        return "show information about the contents of a NAR file";
    }

    void run() override
    {
        list(makeNarAccessor(make_ref<std::string>(readFile(narPath, true))));
    }
};

static RegisterCommand r1(make_ref<CmdLsStore>());
static RegisterCommand r2(make_ref<CmdLsNar>());
<|endoftext|>


<commit_before>#include "nan.h"
#include "nanodbc.h"
#include "picojson.h"

using std::string;

static v8::Persistent<v8::FunctionTemplate> nodbc_constructor;

class NodbcConnection : node::ObjectWrap {
public:
    static void Init();
    static NAN_METHOD(New);
    static NAN_METHOD(IsConnected);
    static NAN_METHOD(Open);
    static NAN_METHOD(Close);
private:
    nanodbc::connection connection;
};

NAN_METHOD(NodbcConnection::New) {
    NanScope();

    NodbcConnection *obj = new NodbcConnection();
    obj->Wrap(args.Holder());

    NanReturnValue(args.Holder());
}

NAN_METHOD(NodbcConnection::IsConnected) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());

    NanReturnValue(NanNew(self->connection.connected()));
}

class OpenWorker : public NanAsyncWorker {
public:
    OpenWorker(NanCallback *callback, nanodbc::connection *connection, string connectionString)
        : NanAsyncWorker(callback), connection(connection), connectionString(connectionString) {}

    void Execute() {
        try {
            connection->connect(connectionString);
        }
        catch (const nanodbc::database_error &err) {
            SetErrorMessage(err.what());
        }
    }

private:
    nanodbc::connection *connection;
    string connectionString;
};

NAN_METHOD(NodbcConnection::Open) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());
    string connectionString(*NanAsciiString(args[0].As<v8::String>()));
    NanCallback *callback = new NanCallback(args[1].As<v8::Function>());

    OpenWorker *worker = new OpenWorker(callback, &self->connection, connectionString);
    worker->SaveToPersistent("database", args.Holder());
    NanAsyncQueueWorker(worker);

    NanReturnUndefined();
}

class CloseWorker : public NanAsyncWorker {
public:
    CloseWorker(NanCallback *callback, nanodbc::connection *connection)
        : NanAsyncWorker(callback), connection(connection) {}

    void Execute() {
        connection->disconnect();
    }

private:
    nanodbc::connection *connection;
};

NAN_METHOD(NodbcConnection::Close) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());
    NanCallback *callback = new NanCallback(args[0].As<v8::Function>());

    CloseWorker *worker = new CloseWorker(callback, &self->connection);
    worker->SaveToPersistent("database", args.Holder());
    NanAsyncQueueWorker(worker);

    NanReturnUndefined();
}

void NodbcConnection::Init() {
    v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(NodbcConnection::New);
    NanAssignPersistent(nodbc_constructor, tpl);
    tpl->SetClassName(NanNew("NodbcConnection"));
    tpl->InstanceTemplate()->SetInternalFieldCount(1);
    NODE_SET_PROTOTYPE_METHOD(tpl, "isConnected", NodbcConnection::IsConnected);
    NODE_SET_PROTOTYPE_METHOD(tpl, "open", NodbcConnection::Open);
    NODE_SET_PROTOTYPE_METHOD(tpl, "close", NodbcConnection::Close);
}

void Init(v8::Handle<v8::Object> target) {
    NodbcConnection::Init();
    target->Set(NanNew("NodbcConnection"),
        NanNew<v8::FunctionTemplate>(nodbc_constructor)->GetFunction());
}

NODE_MODULE(nodbc, Init)
<commit_msg>Add implementation of execute.<commit_after>#include "nan.h"
#include "nanodbc.h"
#include "picojson.h"

using std::string;

static v8::Persistent<v8::FunctionTemplate> nodbc_constructor;

class NodbcConnection : node::ObjectWrap {
public:
    static void Init();
    static NAN_METHOD(New);
    static NAN_METHOD(IsConnected);
    static NAN_METHOD(Open);
    static NAN_METHOD(Close);
    static NAN_METHOD(Execute);
private:
    nanodbc::connection connection;
};

NAN_METHOD(NodbcConnection::New) {
    NanScope();

    NodbcConnection *obj = new NodbcConnection();
    obj->Wrap(args.Holder());

    NanReturnValue(args.Holder());
}

NAN_METHOD(NodbcConnection::IsConnected) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());

    NanReturnValue(NanNew(self->connection.connected()));
}

class OpenWorker : public NanAsyncWorker {
public:
    OpenWorker(NanCallback *callback, nanodbc::connection *connection, string connectionString)
        : NanAsyncWorker(callback), connection(connection), connectionString(connectionString) {}

    void Execute() {
        try {
            connection->connect(connectionString);
        }
        catch (const nanodbc::database_error &err) {
            SetErrorMessage(err.what());
        }
    }

private:
    nanodbc::connection *connection;
    string connectionString;
};

NAN_METHOD(NodbcConnection::Open) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());
    string connectionString(*NanAsciiString(args[0].As<v8::String>()));
    NanCallback *callback = new NanCallback(args[1].As<v8::Function>());

    OpenWorker *worker = new OpenWorker(callback, &self->connection, connectionString);
    worker->SaveToPersistent("database", args.Holder());
    NanAsyncQueueWorker(worker);

    NanReturnUndefined();
}

class CloseWorker : public NanAsyncWorker {
public:
    CloseWorker(NanCallback *callback, nanodbc::connection *connection)
        : NanAsyncWorker(callback), connection(connection) {}

    void Execute() {
        connection->disconnect();
    }

private:
    nanodbc::connection *connection;
};

NAN_METHOD(NodbcConnection::Close) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());
    NanCallback *callback = new NanCallback(args[0].As<v8::Function>());

    CloseWorker *worker = new CloseWorker(callback, &self->connection);
    worker->SaveToPersistent("database", args.Holder());
    NanAsyncQueueWorker(worker);

    NanReturnUndefined();
}

class ExecuteWorker : public NanAsyncWorker {
public:
    ExecuteWorker(NanCallback *callback, nanodbc::connection *connection, string query)
        : NanAsyncWorker(callback), connection(connection), query(query) {}

    void Execute() {
        try {
            nanodbc::result result = nanodbc::execute(*connection, query);

            picojson::array rows;
            const short columns = result.columns();

            while (result.next()) {
                picojson::object row;
                for (short col = 0; col < columns; col++) {
                    row[result.column_name(col)] = picojson::value(result.get<string>(col));
                }
                rows.push_back(picojson::value(row));
            }

            json = picojson::value(rows).serialize();
        }
        catch (const nanodbc::database_error &err) {
            SetErrorMessage(err.what());
        }
    }

    void HandleOKCallback() {
        NanScope();

        v8::Local<v8::Value> argv[] = {
            NanNull(),
            NanNew(json.c_str())
        };

        callback->Call(2, argv);
    };

private:
    nanodbc::connection *connection;
    string query;
    string json;
};

NAN_METHOD(NodbcConnection::Execute) {
    NanScope();

    NodbcConnection *self = ObjectWrap::Unwrap<NodbcConnection>(args.Holder());
    string query(*NanAsciiString(args[0].As<v8::String>()));
    NanCallback *callback = new NanCallback(args[1].As<v8::Function>());

    ExecuteWorker *worker = new ExecuteWorker(callback, &self->connection, query);
    worker->SaveToPersistent("database", args.Holder());
    NanAsyncQueueWorker(worker);

    NanReturnUndefined();
}

void NodbcConnection::Init() {
    v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(NodbcConnection::New);
    NanAssignPersistent(nodbc_constructor, tpl);
    tpl->SetClassName(NanNew("NodbcConnection"));
    tpl->InstanceTemplate()->SetInternalFieldCount(1);
    NODE_SET_PROTOTYPE_METHOD(tpl, "isConnected", NodbcConnection::IsConnected);
    NODE_SET_PROTOTYPE_METHOD(tpl, "open", NodbcConnection::Open);
    NODE_SET_PROTOTYPE_METHOD(tpl, "close", NodbcConnection::Close);
    NODE_SET_PROTOTYPE_METHOD(tpl, "execute", NodbcConnection::Execute);
}

void Init(v8::Handle<v8::Object> target) {
    NodbcConnection::Init();
    target->Set(NanNew("NodbcConnection"),
        NanNew<v8::FunctionTemplate>(nodbc_constructor)->GetFunction());
}

NODE_MODULE(nodbc, Init)
<|endoftext|>


<commit_before>#include <ecto/plasm.hpp>
#include <ecto/tendril.hpp>
#include <ecto/module.hpp>

#include <string>
#include <map>
#include <set>
#include <utility>

//this quiets a deprecated warning
#define BOOST_NO_HASH
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/graph/graphviz.hpp>

using boost::vertex_property_tag;
using boost::adjacency_list;
using boost::vecS;
using boost::bidirectionalS;
using boost::property;
using boost::property_map;
using boost::graph_traits;
namespace ecto
{

  struct ModuleGraph
  {
    typedef std::pair<module::ptr, std::string> _Vertex;
    struct Vertex : public _Vertex
    {
      Vertex() :
        _Vertex()
      {
      }
      Vertex(const module::ptr& p, const std::string& s) :
        _Vertex(p, s)
      {
      }

      struct Tag
      {
        typedef vertex_property_tag kind;
      };
      typedef property<Tag, Vertex> Property;
      size_t uid;
    };
    struct opless
    {
      inline bool operator()(const Vertex&lhs, const Vertex& rhs) const
      {
        return lhs.first.get() < rhs.first.get() || (lhs.first.get() == rhs.first.get() && lhs.second < rhs.second);
      }
    };

    typedef adjacency_list<boost::setS, vecS, boost::bidirectionalS, Vertex::Property> graph_t;
    typedef graph_traits<graph_t> GraphTraits;
    typedef graph_traits<graph_t>::vertex_descriptor Vertex_Desc;

    graph_t graph_, root_graph_;

    void add_edge(module::ptr from_m, const std::string& out_name, module::ptr to_m, const std::string& in_name)
    {
      Vertex from = make_vert(from_m, out_name);
      Vertex to = make_vert(to_m, in_name);
      Vertex root_from = make_vert(from_m);
      Vertex root_to = make_vert(to_m);
      boost::add_edge(root_from.uid, from.uid, graph_);
      boost::add_edge(root_from.uid, root_to.uid, root_graph_);
      boost::add_edge(from.uid, to.uid, graph_);
      boost::add_edge(to.uid, root_to.uid, graph_);
    }

    Vertex& get_vert(size_t uid)
    {
      return boost::get(Vertex::Tag(), graph_)[uid];
    }

    Vertex make_vert(const module::ptr& p, const std::string& s = "root")
    {
      Vertex v(p, s);
      getUID(v);
      get_vert(v.uid) = v;
      return v;
    }

    struct Dirtier
    {
      Dirtier(ModuleGraph&g) :
        graph(g)
      {
      }

      void operator()(const Vertex_Desc& v)
      {
        graph.get_vert(v).first->dirty(true);
        if(graph.graph_.out_edge_list(v).empty())
          return;
        GraphTraits::out_edge_iterator out_i, out_end;
        GraphTraits::edge_descriptor e;
        for (boost::tie(out_i, out_end) = boost::out_edges(v, graph.root_graph_); out_i != out_end; ++out_i)
        {
          e = *out_i;
          Vertex_Desc targ = target(e, graph.root_graph_);
          (*this)(targ);
        }
      }
      ModuleGraph& graph;
    };

    struct Goer
    {
      Goer(ModuleGraph&g) :
        graph(g)
      {
      }
      void operator()(const Vertex_Desc& v)
      {

        Vertex& vert = graph.get_vert(v);
        if (!vert.first->dirty())
          return;
        GraphTraits::in_edge_iterator in_i, in_end;
        GraphTraits::edge_descriptor e;
        if(!graph.graph_.out_edge_list(v).empty())
        for (boost::tie(in_i, in_end) = boost::in_edges(v, graph.root_graph_); in_i != in_end; ++in_i)
        {
          e = *in_i;
          Vertex_Desc targ = boost::source(e, graph.root_graph_);
          (*this)(targ);
        }
        vert.first->Process();
        vert.first->dirty(true);
      }
      ModuleGraph& graph;
    };

    void mark_dirty(module::ptr m)
    {
      Dirtier(*this)(make_vert(m).uid);
    }
    void go(module::ptr m)

    {
      Goer(*this)(make_vert(m).uid);
    }

    typedef std::set<Vertex, opless> module_set_t;
    module_set_t module_set;

    /** Assigns a unique vertex id, from the graph.
     *
     * @param v
     */
    inline void getUID(Vertex& v)
    {
      //std::cout << v.first << v.second << std::endl;
      module_set_t::const_iterator it = module_set.find(v);
      if (it == module_set.end())
      {
        v.uid = boost::add_vertex(graph_);
        module_set.insert(v).second;
      }
      else
        v.uid = it->uid;

    }

  };

  struct plasm::impl
  {

    ModuleGraph modules_;
  };

  plasm::plasm() :
    impl_(new impl)
  {
  }
  void plasm::connect(module::ptr from, const std::string& out_name, module::ptr to, const std::string& in_name)
  {
    impl_->modules_.add_edge(from, out_name, to, in_name);
    from->connect(out_name, to, in_name);
  }

  void plasm::markDirty(module::ptr m)
  {
    // Access the property accessor type for this graph
    impl_->modules_.mark_dirty(m);

  }
  void plasm::go(module::ptr m)
  {
    impl_->modules_.go(m);
  }

  void plasm::viz(std::ostream& out) const
  {
    boost::write_graphviz(out, impl_->modules_.graph_);
  }

  std::string plasm::viz() const
  {
    std::stringstream ss;
    viz(ss);
    return ss.str();
  }

}
<commit_msg>fixme.<commit_after>#include <ecto/plasm.hpp>
#include <ecto/tendril.hpp>
#include <ecto/module.hpp>

#include <string>
#include <map>
#include <set>
#include <utility>

//this quiets a deprecated warning
#define BOOST_NO_HASH
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/graph/graphviz.hpp>

using boost::vertex_property_tag;
using boost::adjacency_list;
using boost::vecS;
using boost::bidirectionalS;
using boost::property;
using boost::property_map;
using boost::graph_traits;
namespace ecto
{

  struct ModuleGraph
  {
    typedef std::pair<module::ptr, std::string> _Vertex;
    struct Vertex : public _Vertex
    {
      Vertex() :
        _Vertex()
      {
      }
      Vertex(const module::ptr& p, const std::string& s) :
        _Vertex(p, s)
      {
      }

      struct Tag
      {
        typedef vertex_property_tag kind;
      };
      typedef property<Tag, Vertex> Property;
      size_t uid;
    };
    struct opless
    {
      inline bool operator()(const Vertex&lhs, const Vertex& rhs) const
      {
        return lhs.first.get() < rhs.first.get() || (lhs.first.get() == rhs.first.get() && lhs.second < rhs.second);
      }
    };

    typedef adjacency_list<boost::setS, vecS, boost::bidirectionalS, Vertex::Property> graph_t;
    typedef graph_traits<graph_t> GraphTraits;
    typedef graph_traits<graph_t>::vertex_descriptor Vertex_Desc;

    graph_t graph_, root_graph_;

    void add_edge(module::ptr from_m, const std::string& out_name, module::ptr to_m, const std::string& in_name)
    {
      Vertex from = make_vert(from_m, out_name);
      Vertex to = make_vert(to_m, in_name);
      Vertex root_from = make_vert(from_m);
      Vertex root_to = make_vert(to_m);
      boost::add_edge(root_from.uid, from.uid, graph_);
      boost::add_edge(root_from.uid, root_to.uid, root_graph_);
      boost::add_edge(from.uid, to.uid, graph_);
      boost::add_edge(to.uid, root_to.uid, graph_);
    }

    Vertex& get_vert(size_t uid)
    {
      return boost::get(Vertex::Tag(), graph_)[uid];
    }

    Vertex make_vert(const module::ptr& p, const std::string& s = "root")
    {
      Vertex v(p, s);
      getUID(v);
      get_vert(v.uid) = v;
      return v;
    }

    struct Dirtier
    {
      Dirtier(ModuleGraph&g) :
        graph(g)
      {
      }

      void operator()(const Vertex_Desc& v)
      {
        graph.get_vert(v).first->dirty(true);
        //fixme!!!
        if(graph.graph_.out_edge_list(v).empty())
          return;
        GraphTraits::out_edge_iterator out_i, out_end;
        GraphTraits::edge_descriptor e;
        for (boost::tie(out_i, out_end) = boost::out_edges(v, graph.root_graph_); out_i != out_end; ++out_i)
        {
          e = *out_i;
          Vertex_Desc targ = target(e, graph.root_graph_);
          (*this)(targ);
        }
      }
      ModuleGraph& graph;
    };

    struct Goer
    {
      Goer(ModuleGraph&g) :
        graph(g)
      {
      }
      void operator()(const Vertex_Desc& v)
      {

        Vertex& vert = graph.get_vert(v);
        if (!vert.first->dirty())
          return;
        GraphTraits::in_edge_iterator in_i, in_end;
        GraphTraits::edge_descriptor e;
        //fixme!!!
        if(!graph.graph_.out_edge_list(v).empty())
        for (boost::tie(in_i, in_end) = boost::in_edges(v, graph.root_graph_); in_i != in_end; ++in_i)
        {
          e = *in_i;
          Vertex_Desc targ = boost::source(e, graph.root_graph_);
          (*this)(targ);
        }
        vert.first->Process();
        vert.first->dirty(true);
      }
      ModuleGraph& graph;
    };

    void mark_dirty(module::ptr m)
    {
      Dirtier(*this)(make_vert(m).uid);
    }
    void go(module::ptr m)

    {
      Goer(*this)(make_vert(m).uid);
    }

    typedef std::set<Vertex, opless> module_set_t;
    module_set_t module_set;

    /** Assigns a unique vertex id, from the graph.
     *
     * @param v
     */
    inline void getUID(Vertex& v)
    {
      //std::cout << v.first << v.second << std::endl;
      module_set_t::const_iterator it = module_set.find(v);
      if (it == module_set.end())
      {
        v.uid = boost::add_vertex(graph_);
        module_set.insert(v).second;
      }
      else
        v.uid = it->uid;

    }

  };

  struct plasm::impl
  {

    ModuleGraph modules_;
  };

  plasm::plasm() :
    impl_(new impl)
  {
  }
  void plasm::connect(module::ptr from, const std::string& out_name, module::ptr to, const std::string& in_name)
  {
    impl_->modules_.add_edge(from, out_name, to, in_name);
    from->connect(out_name, to, in_name);
  }

  void plasm::markDirty(module::ptr m)
  {
    // Access the property accessor type for this graph
    impl_->modules_.mark_dirty(m);

  }
  void plasm::go(module::ptr m)
  {
    impl_->modules_.go(m);
  }

  void plasm::viz(std::ostream& out) const
  {
    boost::write_graphviz(out, impl_->modules_.graph_);
  }

  std::string plasm::viz() const
  {
    std::stringstream ss;
    viz(ss);
    return ss.str();
  }

}
<|endoftext|>


<commit_before>#include "standard.h"
#include "utils.h"
#include "serversocket.h"
#include "logger.cpp"
#include "proxysocket.h"

using namespace std;

ServerSocket mainSocket;
char *remoteUrl;
int remotePort;
Modes mode = CLIENT;

// For closing the sockets safely when Ctrl+C SIGINT is received
void intHandler(int dummy) {
  info("\nClosing socket\n");
  mainSocket.closeSocket();
  exit(0);
}

// To ignore SIGPIPE being carried over to the parent
// When client closes pipe
void pipeHandler(int dummy) {
  info("Connection closed due to SIGPIPE");
}

void exchangeData(ProxySocket& sock) {
    vector<char> buffer((BUFSIZE+5)*sizeof(char));
    vector<char> duffer((BUFSIZE+5)*sizeof(char));

    ProxySocket outsock = ProxySocket(remoteUrl, remotePort,
                                      mode==CLIENT?HTTP:PLAIN);

    bool areTheyStillThere = true;
    setNonBlocking(sock.fd);

    int a, b;

    do {
        a = outsock.recvFromSocket(buffer, 0, b);
        if (a == -1) {
            areTheyStillThere = false;
            break;
        }
        if (a == 0) {
            logger << "Got nothing from remote";
        } else {
            // TODO If sock is HTTP, don't send till there's a request read
            sock.sendFromSocket(buffer, b, a);
            logger << "Sent " << a << " bytes from remote to local";
        }
        buffer[0] = 0;

        a = sock.recvFromSocket(duffer, 0, b);
        if (a == -1) {
            areTheyStillThere = false;
            break;
        }
        if (a == 0) {
            logger << "Got nothing from client";
            // TODO Send empty HTTP requests if outsock is HTTP
        } else {
            outsock.sendFromSocket(duffer, b, a);
            logger << "Sent " << a << " bytes from local to remote";
        }
        duffer[0] = 0;
        sleep(1);
    } while (areTheyStillThere);
}

int main(int argc, char * argv[]) {
    int portNumber, pid;

    signal(SIGINT, intHandler);
    signal(SIGPIPE, pipeHandler);
    signal(SIGCHLD, SIG_IGN);

    // CLI argument parsing
    if (argc != 4 && argc != 5)
        error("Usage format: ./http-server <local port> <remote url> <remotePort>");
    portNumber = atoi(argv[1]);
    remoteUrl = argv[2];
    remotePort = atoi(argv[3]);

    if (argc == 5) {
        if (strcmp(argv[4], "SERVER") == 0) {
            mode = SERVER;
            info("Running as server");
        } else {
            info("Running as client");
        }
    }

    // Class ServerSocket handles the connection logic
    mainSocket.listenOnPort(portNumber);

    // The main loop which receives and handles connections
    while (1) {
        // Accept connections and create a class instance
        // Forks as needed
        mainSocket.connectToSocket(exchangeData, mode);
    }
    return 0;
}
<commit_msg>Decent lag working model, unsynced<commit_after>#include "standard.h"
#include "utils.h"
#include "serversocket.h"
#include "logger.cpp"
#include "proxysocket.h"

using namespace std;

ServerSocket mainSocket;
char *remoteUrl;
int remotePort;
Modes mode = CLIENT;

// For closing the sockets safely when Ctrl+C SIGINT is received
void intHandler(int dummy) {
  info("\nClosing socket\n");
  mainSocket.closeSocket();
  exit(0);
}

// To ignore SIGPIPE being carried over to the parent
// When client closes pipe
void pipeHandler(int dummy) {
  info("Connection closed due to SIGPIPE");
}

void exchangeData(ProxySocket& sock) {
    vector<char> buffer((BUFSIZE+5)*sizeof(char));
    vector<char> duffer((BUFSIZE+5)*sizeof(char));

    ProxySocket outsock = ProxySocket(remoteUrl, remotePort,
                                      mode==CLIENT?HTTP:PLAIN);

    bool areTheyStillThere = true;
    setNonBlocking(sock.fd);

    int a, b;
    bool canIRespond = false;

    do {
        a = outsock.recvFromSocket(buffer, 0, b);
        if (a == -1) {
            areTheyStillThere = false;
            break;
        }
        if (a == 0) {
            logger << "Got nothing from remote";
        } else {
            // TODO If sock is HTTP, don't send till there's a request
            // read
            // if (sock.protocol == PLAIN || canIRespond) {
            //     sock.sendFromSocket(buffer, b, a);
            //     canIRespond = false;
            // }
            sock.sendFromSocket(buffer, b, a);
            logger << "Sent " << a << " bytes from remote to local";
        }
        buffer[0] = 0;

        a = sock.recvFromSocket(duffer, 0, b);
        if (a == -1) {
            areTheyStillThere = false;
            break;
        }
        if (a == 0) {
            logger << "Got nothing from client";
            // if (outsock.protocol == HTTP) {
            //     outsock.sendEmptyHttp();
            // }
            // TODO Send empty HTTP requests if outsock is HTTP
        } else {
            outsock.sendFromSocket(duffer, b, a);
            logger << "Sent " << a << " bytes from local to remote";
        }
        duffer[0] = 0;
        usleep(100000);
    } while (areTheyStillThere);
}

int main(int argc, char * argv[]) {
    int portNumber, pid;

    signal(SIGINT, intHandler);
    signal(SIGPIPE, pipeHandler);
    signal(SIGCHLD, SIG_IGN);

    // CLI argument parsing
    if (argc != 4 && argc != 5)
        error("Usage format: ./http-server <local port> <remote url> <remotePort>");
    portNumber = atoi(argv[1]);
    remoteUrl = argv[2];
    remotePort = atoi(argv[3]);

    if (argc == 5) {
        if (strcmp(argv[4], "SERVER") == 0) {
            mode = SERVER;
            info("Running as server");
        } else {
            info("Running as client");
        }
    }

    // Class ServerSocket handles the connection logic
    mainSocket.listenOnPort(portNumber);

    // The main loop which receives and handles connections
    while (1) {
        // Accept connections and create a class instance
        // Forks as needed
        mainSocket.connectToSocket(exchangeData, mode);
    }
    return 0;
}
<|endoftext|>


<commit_before>// @(#)root/gl:$Id$
// Author: Bertrand Bellenot 2008

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGLOverlayButton.h"
#include "TColor.h"
#include "TMath.h"

#include <TGLRnrCtx.h>
#include <TGLIncludes.h>
#include <TGLSelectRecord.h>
#include <TGLUtil.h>
#include <TGLCamera.h>
#include <TGLViewerBase.h>

//______________________________________________________________________________
//
//
// GL-overaly button.
//
//

ClassImp(TGLOverlayButton);

//______________________________________________________________________________
TGLOverlayButton::TGLOverlayButton(TGLViewerBase *parent, const char *text,
   Float_t posx, Float_t posy, Float_t width, Float_t height) :
   TGLOverlayElement(),
   fText(text),
   fActiveID(-1),
   fBackColor(0x8080ff),
   fTextColor(0xffffff),
   fNormAlpha(0.2),
   fHighAlpha(1.0),
   fPosX(posx),
   fPosY(posy),
   fWidth(width),
   fHeight(height)
{
   // Constructor.

   if (parent)
      parent->AddOverlayElement(this);
}

/******************************************************************************/
void TGLOverlayButton::Render(TGLRnrCtx& rnrCtx)
{
   // Render the overlay elements.

   Float_t r, g, b;
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();
   if (rnrCtx.Selection())
   {
      TGLRect rect(*rnrCtx.GetPickRectangle());
      rnrCtx.GetCamera()->WindowToViewport(rect);
      gluPickMatrix(rect.X(), rect.Y(), rect.Width(), rect.Height(),
                    (Int_t*) rnrCtx.GetCamera()->RefViewport().CArr());
   }
   const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
   glOrtho(vp.X(), vp.Width(), vp.Y(), vp.Height(), 0, 1);
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity();

   Float_t offset = (fPosY >= 0.0)? 0.0 : vp.Height()-fHeight;

   TGLCapabilitySwitch lights_off(GL_LIGHTING, kFALSE);
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glShadeModel(GL_FLAT);
   glClearColor(0.0, 0.0, 0.0, 0.0);

   // Button rendering
   {
      TGLCapabilitySwitch move_to_back(GL_POLYGON_OFFSET_FILL, kTRUE);
      glPolygonOffset(0.5f, 0.5f);

      glPushMatrix();
      glTranslatef(fPosX, offset+fPosY, 0);
      // First the border, same color as text
      TColor::Pixel2RGB(fTextColor, r, g, b);
      (fActiveID == 1) ? TGLUtil::Color4f(r, g, b, fHighAlpha):TGLUtil::Color4f(r, g, b, fNormAlpha);
      TGLUtil::LineWidth(1);
      glBegin(GL_LINE_LOOP);
      glVertex2f(0.0, 0.0);
      glVertex2f(0.0, fHeight);
      glVertex2f(fWidth, fHeight);
      glVertex2f(fWidth, 0.0);
      glEnd();
      // then the button itself, with its own color
      // decrease a bit the highlight, to avoid bad effects...
      TColor::Pixel2RGB(fBackColor, r, g, b);
      (fActiveID == 1) ? TGLUtil::Color4f(r, g, b, fHighAlpha * 0.8):TGLUtil::Color4f(r, g, b, fNormAlpha);
      glBegin(GL_QUADS);
      glVertex2f(0.0, 0.0);
      glVertex2f(0.0, fHeight);
      glVertex2f(fWidth, fHeight);
      glVertex2f(fWidth, 0.0);
      glEnd();
      glPopMatrix();
   }

   // Text rendering
   {
      rnrCtx.RegisterFontNoScale(TMath::Nint(fHeight*0.8), "arial",  TGLFont::kPixmap, fFont);
      fFont.PreRender(kFALSE);

      TColor::Pixel2RGB(fTextColor, r, g, b);
      (fActiveID == 1) ? TGLUtil::Color4f(r, g, b, fHighAlpha):TGLUtil::Color4f(r, g, b, fNormAlpha);
      glPushMatrix();
      glTranslatef(fPosX+(fWidth/2.0), offset+fPosY+(fHeight/2.0), 0);
      Float_t llx, lly, llz, urx, ury, urz;
      fFont.BBox(fText.Data(), llx, lly, llz, urx, ury, urz);
      glRasterPos2i(0, 0);
      glBitmap(0, 0, 0, 0, -urx*0.5f, -ury*0.4f, 0);
      fFont.Render(fText.Data());
      fFont.PostRender();
      glPopMatrix();
   }

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
}

//______________________________________________________________________________
void TGLOverlayButton::Clicked(TGLViewerBase *viewer)
{
   // Emits "Clicked(TGLViewerBase*)" signal.
   // Called when user click on the GL button.

   Emit("Clicked(TGLViewerBase*)", (Long_t)viewer);
}

/******************************************************************************/
// Virtual event handlers from TGLOverlayElement
/******************************************************************************/

//______________________________________________________________________________
Bool_t TGLOverlayButton::Handle(TGLRnrCtx         & rnrCtx,
                               TGLOvlSelectRecord & rec,
                               Event_t            * event)
{
   // Handle overlay event.
   // Return TRUE if event was handled.

   if (event->fCode != kButton1) {
      return kFALSE;
   }
   switch (event->fType) {
      case kButtonPress:
         if (rec.GetItem(1) == 1) {
            return kTRUE;
         }
         break;
      case kButtonRelease:
         if (rec.GetItem(1) == 1) {
            Clicked(rnrCtx.GetViewer());
            return kTRUE;
         }
         break;
      default:
         break;
   }
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGLOverlayButton::MouseEnter(TGLOvlSelectRecord& /*rec*/)
{
   // Mouse has entered overlay area.

   fActiveID = 1;
   return kTRUE;
}

//______________________________________________________________________________
void TGLOverlayButton::MouseLeave()
{
   // Mouse has left overlay area.

   fActiveID = -1;
}
<commit_msg>From Bertrand: Fix gl-name handling, improve text centering.<commit_after>// @(#)root/gl:$Id$
// Author: Bertrand Bellenot 2008

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGLOverlayButton.h"
#include "TColor.h"
#include "TMath.h"

#include <TGLRnrCtx.h>
#include <TGLIncludes.h>
#include <TGLSelectRecord.h>
#include <TGLUtil.h>
#include <TGLCamera.h>
#include <TGLViewerBase.h>

//______________________________________________________________________________
//
//
// GL-overaly button.
//
//

ClassImp(TGLOverlayButton);

//______________________________________________________________________________
TGLOverlayButton::TGLOverlayButton(TGLViewerBase *parent, const char *text,
   Float_t posx, Float_t posy, Float_t width, Float_t height) :
   TGLOverlayElement(),
   fText(text),
   fActiveID(-1),
   fBackColor(0x8080ff),
   fTextColor(0xffffff),
   fNormAlpha(0.2),
   fHighAlpha(1.0),
   fPosX(posx),
   fPosY(posy),
   fWidth(width),
   fHeight(height)
{
   // Constructor.

   if (parent)
      parent->AddOverlayElement(this);
}

/******************************************************************************/
void TGLOverlayButton::Render(TGLRnrCtx& rnrCtx)
{
   // Render the overlay elements.

   Float_t r, g, b;
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();
   if (rnrCtx.Selection())
   {
      TGLRect rect(*rnrCtx.GetPickRectangle());
      rnrCtx.GetCamera()->WindowToViewport(rect);
      gluPickMatrix(rect.X(), rect.Y(), rect.Width(), rect.Height(),
                    (Int_t*) rnrCtx.GetCamera()->RefViewport().CArr());
   }
   const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
   glOrtho(vp.X(), vp.Width(), vp.Y(), vp.Height(), 0, 1);
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity();

   Float_t offset = (fPosY >= 0.0)? 0.0 : vp.Height()-fHeight;

   TGLCapabilitySwitch lights_off(GL_LIGHTING, kFALSE);
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glShadeModel(GL_FLAT);
   glClearColor(0.0, 0.0, 0.0, 0.0);
   glPushName(1);

   // Button rendering
   {
      TGLCapabilitySwitch move_to_back(GL_POLYGON_OFFSET_FILL, kTRUE);
      glPolygonOffset(0.5f, 0.5f);
      glPushMatrix();
      glTranslatef(fPosX, offset+fPosY, 0);
      // First the border, same color as text
      TColor::Pixel2RGB(fTextColor, r, g, b);
      (fActiveID == 1) ? TGLUtil::Color4f(r, g, b, fHighAlpha):TGLUtil::Color4f(r, g, b, fNormAlpha);
      TGLUtil::LineWidth(1);
      glBegin(GL_LINE_LOOP);
      glVertex2f(0.0, 0.0);
      glVertex2f(0.0, fHeight);
      glVertex2f(fWidth, fHeight);
      glVertex2f(fWidth, 0.0);
      glEnd();
      // then the button itself, with its own color
      // decrease a bit the highlight, to avoid bad effects...
      TColor::Pixel2RGB(fBackColor, r, g, b);
      (fActiveID == 1) ? TGLUtil::Color4f(r, g, b, fHighAlpha * 0.8):TGLUtil::Color4f(r, g, b, fNormAlpha);
      glBegin(GL_QUADS);
      glVertex2f(0.0, 0.0);
      glVertex2f(0.0, fHeight);
      glVertex2f(fWidth, fHeight);
      glVertex2f(fWidth, 0.0);
      glEnd();
      glPopMatrix();
   }

   // Text rendering
   {
      rnrCtx.RegisterFontNoScale(TMath::Nint(fHeight*0.8), "arial",  TGLFont::kPixmap, fFont);
      fFont.PreRender(kFALSE);

      TColor::Pixel2RGB(fTextColor, r, g, b);
      (fActiveID == 1) ? TGLUtil::Color4f(r, g, b, fHighAlpha):TGLUtil::Color4f(r, g, b, fNormAlpha);
      glPushMatrix();
      glTranslatef(fPosX+(fWidth/2.0), offset+fPosY+(fHeight/2.0), 0);
      Float_t llx, lly, llz, urx, ury, urz;
      fFont.BBox(fText.Data(), llx, lly, llz, urx, ury, urz);
      glRasterPos2i(0, 0);
      glBitmap(0, 0, 0, 0, -urx*0.5f, -ury*0.5f, 0);
      fFont.Render(fText.Data());
      fFont.PostRender();
      glPopMatrix();
   }
   glPopName();

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
}

//______________________________________________________________________________
void TGLOverlayButton::Clicked(TGLViewerBase *viewer)
{
   // Emits "Clicked(TGLViewerBase*)" signal.
   // Called when user click on the GL button.

   Emit("Clicked(TGLViewerBase*)", (Long_t)viewer);
}

/******************************************************************************/
// Virtual event handlers from TGLOverlayElement
/******************************************************************************/

//______________________________________________________________________________
Bool_t TGLOverlayButton::Handle(TGLRnrCtx         & rnrCtx,
                               TGLOvlSelectRecord & rec,
                               Event_t            * event)
{
   // Handle overlay event.
   // Return TRUE if event was handled.

   if (event->fCode != kButton1) {
      return kFALSE;
   }
   switch (event->fType) {
      case kButtonPress:
         if (rec.GetItem(1) == 1) {
            return kTRUE;
         }
         break;
      case kButtonRelease:
         if (rec.GetItem(1) == 1) {
            Clicked(rnrCtx.GetViewer());
            return kTRUE;
         }
         break;
      default:
         break;
   }
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGLOverlayButton::MouseEnter(TGLOvlSelectRecord& /*rec*/)
{
   // Mouse has entered overlay area.

   fActiveID = 1;
   return kTRUE;
}

//______________________________________________________________________________
void TGLOverlayButton::MouseLeave()
{
   // Mouse has left overlay area.

   fActiveID = -1;
}
<|endoftext|>


<commit_before>#include <netinet/in.h>
#include <rapid/rapid.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <string>
#include <thread>

#include <openssl/err.h>
#include <openssl/ssl.h>

namespace rapid {

class TlsManager {
 public:
  static TlsManager *instance() {
    static TlsManager *_instance = nullptr;
    if (_instance) {
      return _instance;
    }
    _instance = new TlsManager;
    return _instance;
  }

  bool failed() const { return _failed; }
  bool succeed() const { return !_failed; }

  void init() {
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    auto method = TLSv1_server_method();
    auto ctx = SSL_CTX_new(method);
    if (!ctx) {
      _failed = true;
      ERR_print_errors_fp(stderr);
      return;
    }
    _ctx = ctx;
  }

  bool load_certificate(const std::string &cert_path) {
    if (_ctx == nullptr) {
      return false;
    }
    if (SSL_CTX_use_certificate_file(_ctx, cert_path.c_str(),
                                     SSL_FILETYPE_PEM) <= 0) {
      return false;
    }
    return true;
  }

  bool load_private_key(const std::string &private_key_path) {
    if (_ctx == nullptr) {
      return false;
    }
    if (SSL_CTX_use_PrivateKey_file(_ctx, private_key_path.c_str(),
                                    SSL_FILETYPE_PEM) <= 0) {
      return false;
    }
    return true;
  }

  bool verify_private_key() {
    if (_ctx == nullptr) {
      return false;
    }
    if (!SSL_CTX_check_private_key(_ctx)) {
      return false;
    }
    return true;
  }

  bool recv_tls(int peer, const std::function<ResponsePtr(Request &)> &fn) {
    if (_ctx == nullptr) {
      return false;
    }

    SSL *ssl = SSL_new(_ctx);
    SSL_set_fd(ssl, peer);
    if (SSL_accept(ssl) == -1) {
      // ...
    } else {
      char buf[4096];
      auto bytes = SSL_read(ssl, buf, sizeof(buf));
      if (0 < bytes) {
        buf[bytes] = 0;
        Request request(buf);
        auto response = fn(request);
        auto response_s = response->message();
        SSL_write(ssl, response_s->c_str(),
                  static_cast<int>(response_s->size()));
      }
    }
    SSL_free(ssl);

    return true;
  }

 private:
  bool _failed = false;
  SSL_CTX *_ctx = nullptr;
};

Server::Server() {}

void Server::set_port(int port) { _port = port; }

void Server::use_tls() { _use_tls = true; }

void Server::set_tls_certificate_path(const std::string &path) {
  _cert_path = path;
}

void Server::set_tls_private_key_path(const std::string &path) {
  _pk_path = path;
}

void Server::run() {
  assert(_port != kUndefinedPort);

  auto th = std::thread([&] {
    _stopped = false;

    boot();

    while (!_stop_requested) {
      dispatch_http_request(_sock);
    }

    close(_sock);
    _sock = -1;

    _stopped = true;
  });

  th.detach();
}

void Server::stop() { _stop_requested = true; }

bool Server::stopped() const { return _stopped; }

void Server::get(const std::string &pattern, const Handler &handler) {
  _dispatcher.add(Route(Method::Get, pattern, handler));
}

void Server::post(const std::string &pattern, const Handler &handler) {
  _dispatcher.add(Route(Method::Post, pattern, handler));
}

void Server::boot() {
  if (_sock == -1) {
    if (_use_tls) {
      TlsManager::instance()->init();
      TlsManager::instance()->load_certificate(_cert_path);
      TlsManager::instance()->load_private_key(_pk_path);
      TlsManager::instance()->verify_private_key();
    }

    _sock = socket(AF_INET, SOCK_STREAM, 0);
    int flag = 1;
    setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(_port);
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_len = sizeof(addr);
    bind(_sock, (struct sockaddr *)&addr, sizeof(addr));
    listen(_sock, 5);
  }
}

void Server::dispatch_http_request(int socket) {
  struct sockaddr_in client_addr;
  auto len = sizeof(client_addr);
  auto peer =
      accept(socket, (struct sockaddr *)&client_addr, (socklen_t *)&len);

  if (_use_tls) {
    TlsManager::instance()->recv_tls(peer,
                                     [&](Request &request) -> ResponsePtr {
                                       return _dispatcher.dispatch(request);
                                     });
  } else {
    char inbuf[4096];
    auto inlen = recv(peer, inbuf, sizeof(inbuf), 0);
    inbuf[inlen] = '\0';

    Request request(inbuf);
    auto response = _dispatcher.dispatch(request);
    auto response_s = response->message();
    write(peer, response_s->c_str(), response_s->size());
  }
  close(peer);
}
}<commit_msg>remove sin_len<commit_after>#include <netinet/in.h>
#include <rapid/rapid.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <string>
#include <thread>

#include <openssl/err.h>
#include <openssl/ssl.h>

namespace rapid {

class TlsManager {
 public:
  static TlsManager *instance() {
    static TlsManager *_instance = nullptr;
    if (_instance) {
      return _instance;
    }
    _instance = new TlsManager;
    return _instance;
  }

  bool failed() const { return _failed; }
  bool succeed() const { return !_failed; }

  void init() {
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    auto method = TLSv1_server_method();
    auto ctx = SSL_CTX_new(method);
    if (!ctx) {
      _failed = true;
      ERR_print_errors_fp(stderr);
      return;
    }
    _ctx = ctx;
  }

  bool load_certificate(const std::string &cert_path) {
    if (_ctx == nullptr) {
      return false;
    }
    if (SSL_CTX_use_certificate_file(_ctx, cert_path.c_str(),
                                     SSL_FILETYPE_PEM) <= 0) {
      return false;
    }
    return true;
  }

  bool load_private_key(const std::string &private_key_path) {
    if (_ctx == nullptr) {
      return false;
    }
    if (SSL_CTX_use_PrivateKey_file(_ctx, private_key_path.c_str(),
                                    SSL_FILETYPE_PEM) <= 0) {
      return false;
    }
    return true;
  }

  bool verify_private_key() {
    if (_ctx == nullptr) {
      return false;
    }
    if (!SSL_CTX_check_private_key(_ctx)) {
      return false;
    }
    return true;
  }

  bool recv_tls(int peer, const std::function<ResponsePtr(Request &)> &fn) {
    if (_ctx == nullptr) {
      return false;
    }

    SSL *ssl = SSL_new(_ctx);
    SSL_set_fd(ssl, peer);
    if (SSL_accept(ssl) == -1) {
      // ...
    } else {
      char buf[4096];
      auto bytes = SSL_read(ssl, buf, sizeof(buf));
      if (0 < bytes) {
        buf[bytes] = 0;
        Request request(buf);
        auto response = fn(request);
        auto response_s = response->message();
        SSL_write(ssl, response_s->c_str(),
                  static_cast<int>(response_s->size()));
      }
    }
    SSL_free(ssl);

    return true;
  }

 private:
  bool _failed = false;
  SSL_CTX *_ctx = nullptr;
};

Server::Server() {}

void Server::set_port(int port) { _port = port; }

void Server::use_tls() { _use_tls = true; }

void Server::set_tls_certificate_path(const std::string &path) {
  _cert_path = path;
}

void Server::set_tls_private_key_path(const std::string &path) {
  _pk_path = path;
}

void Server::run() {
  assert(_port != kUndefinedPort);

  auto th = std::thread([&] {
    _stopped = false;

    boot();

    while (!_stop_requested) {
      dispatch_http_request(_sock);
    }

    close(_sock);
    _sock = -1;

    _stopped = true;
  });

  th.detach();
}

void Server::stop() { _stop_requested = true; }

bool Server::stopped() const { return _stopped; }

void Server::get(const std::string &pattern, const Handler &handler) {
  _dispatcher.add(Route(Method::Get, pattern, handler));
}

void Server::post(const std::string &pattern, const Handler &handler) {
  _dispatcher.add(Route(Method::Post, pattern, handler));
}

void Server::boot() {
  if (_sock == -1) {
    if (_use_tls) {
      TlsManager::instance()->init();
      TlsManager::instance()->load_certificate(_cert_path);
      TlsManager::instance()->load_private_key(_pk_path);
      TlsManager::instance()->verify_private_key();
    }

    _sock = socket(AF_INET, SOCK_STREAM, 0);
    int flag = 1;
    setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(_port);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(_sock, (struct sockaddr *)&addr, sizeof(addr));
    listen(_sock, 5);
  }
}

void Server::dispatch_http_request(int socket) {
  struct sockaddr_in client_addr;
  auto len = sizeof(client_addr);
  auto peer =
      accept(socket, (struct sockaddr *)&client_addr, (socklen_t *)&len);

  if (_use_tls) {
    TlsManager::instance()->recv_tls(peer,
                                     [&](Request &request) -> ResponsePtr {
                                       return _dispatcher.dispatch(request);
                                     });
  } else {
    char inbuf[4096];
    auto inlen = recv(peer, inbuf, sizeof(inbuf), 0);
    inbuf[inlen] = '\0';

    Request request(inbuf);
    auto response = _dispatcher.dispatch(request);
    auto response_s = response->message();
    write(peer, response_s->c_str(), response_s->size());
  }
  close(peer);
}
}
<|endoftext|>


<commit_before>#include <franka/robot.h>

#include <Poco/Net/DatagramSocket.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/StreamSocket.h>
#include <Poco/Timespan.h>
#include <chrono>
#include <iostream>
#include <sstream>

#include "message_types.h"
#include "network.h"

namespace franka {

class Robot::Impl {
 public:
  explicit Impl(const std::string& frankaAddress);
  ~Impl();

  bool waitForRobotState();
  const RobotState& getRobotState() const;
  ServerVersion getServerVersion() const;

 private:
  const uint16_t kFranka_port_tcp_;
  const uint16_t kRiLibraryVersion_;
  const std::chrono::seconds kTimeout_;

  uint16_t ri_version_;
  RobotState robot_state_;

  Poco::Net::StreamSocket tcp_socket_;
  Poco::Net::DatagramSocket udp_socket_;
};

Robot::Robot(const std::string& frankaAddress)
    : impl_(new Robot::Impl(frankaAddress)) {}

// Has to be declared here, as the Impl type is incomplete in the header
Robot::~Robot() = default;

bool Robot::waitForRobotState() {
  return impl_->waitForRobotState();
}

const RobotState& Robot::getRobotState() const {
  return impl_->getRobotState();
}

Robot::ServerVersion Robot::getServerVersion() const {
  return impl_->getServerVersion();
}

NetworkException::NetworkException(std::string const& message)
    : std::runtime_error(message) {}

ProtocolException::ProtocolException(std::string const& message)
    : std::runtime_error(message) {}

IncompatibleVersionException::IncompatibleVersionException(
    std::string const& message)
    : std::runtime_error(message) {}

/* Implementation */

Robot::Impl::Impl(const std::string& frankaAddress)
    : kFranka_port_tcp_{1337},
      kRiLibraryVersion_{1},
      kTimeout_{5},
      ri_version_{0},
      robot_state_{},
      tcp_socket_{},
      udp_socket_{} {
  try {
    tcp_socket_.connect({frankaAddress, kFranka_port_tcp_},
                        Poco::Timespan(kTimeout_.count(), 0));
    tcp_socket_.setBlocking(true);
    tcp_socket_.setSendTimeout(Poco::Timespan(kTimeout_.count(), 0));
    tcp_socket_.setReceiveTimeout(Poco::Timespan(kTimeout_.count(), 0));

    udp_socket_.setReceiveTimeout(Poco::Timespan(kTimeout_.count(), 0));
    udp_socket_.bind({"0.0.0.0", 0});

    message_types::ConnectRequest connect_request;
    connect_request.function_id = message_types::FunctionId::kConnect;
    connect_request.ri_library_version = kRiLibraryVersion_;
    connect_request.udp_port = udp_socket_.address().port();

    tcp_socket_.sendBytes(&connect_request, sizeof(connect_request));

    message_types::ConnectReply connect_reply;
    readObject(tcp_socket_, connect_reply, kTimeout_);

    if (connect_reply.status_code !=
        message_types::ConnectReply::StatusCode::kSuccess) {
      if (connect_reply.status_code == message_types::ConnectReply::StatusCode::
                                           kIncompatibleLibraryVersion) {
        std::stringstream message;
        message << "libfranka: incompatible library version. "
                << "Server version: " << connect_reply.ri_version
                << "Library version: " << kRiLibraryVersion_;
        throw IncompatibleVersionException(message.str());
      }
      throw ProtocolException("libfranka: protocol error");
    }
    ri_version_ = connect_reply.ri_version;
  } catch (Poco::TimeoutException const& e) {
    throw NetworkException("libfranka: FRANKA connection timeout");
  } catch (Poco::Exception const& e) {
    throw NetworkException(std::string{"libfranka: FRANKA connection: "} +
                           e.what());
  }
}

Robot::Impl::~Impl() {
  tcp_socket_.shutdown();
  tcp_socket_.close();
  udp_socket_.close();
}

bool Robot::Impl::waitForRobotState() {
  try {
    Poco::Net::SocketAddress server_address;
    int bytes_received = udp_socket_.receiveFrom(
        &robot_state_, sizeof(robot_state_), server_address, 0);
    if (bytes_received == sizeof(robot_state_)) {
      return true;
    }
    if (bytes_received == 0) {
      return false;
    }
    throw ProtocolException("libfranka:: incorrect object size");
  } catch (Poco::TimeoutException const& e) {
    throw NetworkException("libfranka: robot state read timeout");
  } catch (Poco::Net::NetException const& e) {
    throw NetworkException(std::string{"libfranka: robot state read: "} +
                           e.what());
  }
}

const RobotState& Robot::Impl::getRobotState() const {
  return robot_state_;
}

Robot::ServerVersion Robot::Impl::getServerVersion() const {
  return ri_version_;
}

}  // namespace franka
<commit_msg>Simplify tcp receive.<commit_after>#include <franka/robot.h>

#include <Poco/Net/DatagramSocket.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/StreamSocket.h>
#include <chrono>
#include <iostream>
#include <sstream>

#include "message_types.h"

namespace franka {

class Robot::Impl {
 public:
  explicit Impl(const std::string& frankaAddress);
  ~Impl();

  bool waitForRobotState();
  const RobotState& getRobotState() const;
  ServerVersion getServerVersion() const;

 protected:
  // Can throw NetworkException and ProtocolException
  template <class T>
  void tcpReceiveObject(T& object);

 private:
  const uint16_t kFranka_port_tcp_;
  const uint16_t kRiLibraryVersion_;
  const std::chrono::seconds kTimeout_;

  uint16_t ri_version_;
  RobotState robot_state_;

  Poco::Net::StreamSocket tcp_socket_;
  Poco::Net::DatagramSocket udp_socket_;
};

Robot::Robot(const std::string& frankaAddress)
    : impl_(new Robot::Impl(frankaAddress)) {}

// Has to be declared here, as the Impl type is incomplete in the header
Robot::~Robot() = default;

bool Robot::waitForRobotState() {
  return impl_->waitForRobotState();
}

const RobotState& Robot::getRobotState() const {
  return impl_->getRobotState();
}

Robot::ServerVersion Robot::getServerVersion() const {
  return impl_->getServerVersion();
}

NetworkException::NetworkException(std::string const& message)
    : std::runtime_error(message) {}

ProtocolException::ProtocolException(std::string const& message)
    : std::runtime_error(message) {}

IncompatibleVersionException::IncompatibleVersionException(
    std::string const& message)
    : std::runtime_error(message) {}

/* Implementation */

Robot::Impl::Impl(const std::string& frankaAddress)
    : kFranka_port_tcp_{1337},
      kRiLibraryVersion_{1},
      kTimeout_{5},
      ri_version_{0},
      robot_state_{},
      tcp_socket_{},
      udp_socket_{} {
  try {
    tcp_socket_.connect({frankaAddress, kFranka_port_tcp_},
                        Poco::Timespan(kTimeout_.count(), 0));
    tcp_socket_.setBlocking(true);
    tcp_socket_.setSendTimeout(Poco::Timespan(kTimeout_.count(), 0));
    tcp_socket_.setReceiveTimeout(Poco::Timespan(kTimeout_.count(), 0));

    udp_socket_.setReceiveTimeout(Poco::Timespan(kTimeout_.count(), 0));
    udp_socket_.bind({"0.0.0.0", 0});

    message_types::ConnectRequest connect_request;
    connect_request.function_id = message_types::FunctionId::kConnect;
    connect_request.ri_library_version = kRiLibraryVersion_;
    connect_request.udp_port = udp_socket_.address().port();

    tcp_socket_.sendBytes(&connect_request, sizeof(connect_request));

    message_types::ConnectReply connect_reply;
    tcpReceiveObject(connect_reply);

    if (connect_reply.status_code !=
        message_types::ConnectReply::StatusCode::kSuccess) {
      if (connect_reply.status_code == message_types::ConnectReply::StatusCode::
                                           kIncompatibleLibraryVersion) {
        std::stringstream message;
        message << "libfranka: incompatible library version. "
                << "Server version: " << connect_reply.ri_version
                << "Library version: " << kRiLibraryVersion_;
        throw IncompatibleVersionException(message.str());
      }
      throw ProtocolException("libfranka: protocol error");
    }
    ri_version_ = connect_reply.ri_version;
  } catch (Poco::Net::NetException const& e) {
    throw NetworkException(std::string{"libfranka: FRANKA connection error: "} +
                           e.what());
  } catch (Poco::TimeoutException const& e) {
    throw NetworkException("libfranka: FRANKA connection timeout");
  } catch (Poco::Exception const& e) {
    throw NetworkException(std::string{"libfranka: "} + e.what());
  }
}

Robot::Impl::~Impl() {
  tcp_socket_.shutdown();
  tcp_socket_.close();
  udp_socket_.close();
}

bool Robot::Impl::waitForRobotState() {
  try {
    Poco::Net::SocketAddress server_address;
    int bytes_received = udp_socket_.receiveFrom(
        &robot_state_, sizeof(robot_state_), server_address, 0);
    if (bytes_received == sizeof(robot_state_)) {
      return true;
    }
    if (bytes_received == 0) {
      return false;
    }
    throw ProtocolException("libfranka:: incorrect object size");
  } catch (Poco::TimeoutException const& e) {
    throw NetworkException("libfranka: robot state read timeout");
  } catch (Poco::Net::NetException const& e) {
    throw NetworkException(std::string{"libfranka: robot state read: "} +
                           e.what());
  }
}

const RobotState& Robot::Impl::getRobotState() const {
  return robot_state_;
}

Robot::ServerVersion Robot::Impl::getServerVersion() const {
  return ri_version_;
}

template <class T>
void Robot::Impl::tcpReceiveObject(T& object) {
  try {
    int rv = tcp_socket_.receiveBytes(&object, sizeof(object));
    if (rv == 0) {
      throw NetworkException("libfranka:: FRANKA connection closed");
    } else if (rv != sizeof(object)) {
      throw ProtocolException("libfranka:: incorrect object size");
    }
  } catch (Poco::Net::NetException const& e) {
    throw NetworkException(std::string{"libfranka: FRANKA connection error: "} +
                           e.what());
  } catch (Poco::TimeoutException const& e) {
    throw NetworkException("libfranka: FRANKA connection timeout");
  }
}

}  // namespace franka
<|endoftext|>