<commit_before>#include <TGUI/TGUI.hpp>
#include <vili/Vili.hpp>

#include "System/Window.hpp"
#include <Editor/MapEditor.hpp>
#include <Modes/Game.hpp>
#include <Modes/Menu.hpp>
#include <Modes/Toolkit.hpp>
#include <System/Config.hpp>
#include <System/Loaders.hpp>
#include <System/Path.hpp>
#include <Utils/StringUtils.hpp>
#include <thread>

namespace obe::Modes
{
    void scrollPanel(tgui::Panel::Ptr panel, tgui::Scrollbar::Ptr scrollbar)
    {
        static int previousScrolbarValue = 0;
        const int distanceToMove =
            previousScrolbarValue - scrollbar->getValue();

        for (auto& widget : panel->getWidgets())
            widget->setPosition(widget->getPosition().x,
                                widget->getPosition().y + distanceToMove);

        previousScrolbarValue = scrollbar->getValue();
    }

    void chooseMapAddMaps(tgui::Panel::Ptr middlePanel,
                          tgui::Scrollbar::Ptr scrollbar,
                          tgui::Theme& baseTheme, std::string& currentMap)
    {
        int scrollBoxSize = 0;

        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);

        middlePanel->removeAllWidgets();

        std::vector<std::string> allMapsTemp;
        System::Path("Data/Maps")
            .loadAll(System::Loaders::filePathLoader, allMapsTemp);
        std::vector<std::string> allMaps;
        for (int i = 0; i < allMapsTemp.size(); i++)
        {
            if (Utils::String::endsWith(allMapsTemp[i], ".map.vili"))
                allMaps.push_back(allMapsTemp[i]);
        }
        for (int i = 0; i < allMaps.size(); i++)
        {
            vili::ViliParser mapInfoParser;
            mapInfoParser.setQuickLookAttributes({"Meta"});
            System::Path("Data/Maps")
                .add(allMaps[i])
                .load(System::Loaders::dataLoader, mapInfoParser);
            const std::string filename = allMaps[i];
            std::string levelName = "???";

            if (mapInfoParser->contains(vili::NodeType::ComplexNode, "Meta"))
            {
                if (mapInfoParser.at("Meta").contains(vili::NodeType::DataNode,
                                                      "name"))
                    levelName = mapInfoParser.at("Meta")
                                    .getDataNode("name")
                                    .get<std::string>();
            }

            tgui::Button::Ptr selectMapButton = tgui::Button::create();
            middlePanel->add(selectMapButton);
            selectMapButton->setText(
                levelName + " (" +
                filename.substr(0, allMapsTemp[i].size() - 9) + ")");
            selectMapButton->setRenderer(
                baseTheme.getRenderer("MapSelectButton"));
            selectMapButton->setSize("100%", "20%");
            selectMapButton->setPosition("0", i * selectMapButton->getSize().y);
            selectMapButton->connect(
                "pressed", [&currentMap, filename] { currentMap = filename; });
            scrollBoxSize += selectMapButton->getSize().y - 1;
        }
        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);
    }

    void createLevel(tgui::EditBox::Ptr input)
    {
        const std::string newLevelName = input->getText();
        if (newLevelName != "")
        {
            if (!Utils::File::fileExists(System::Path("Data/Maps")
                                             .add(newLevelName + ".map.vili")
                                             .getPath(0)
                                             .toString()))
            {
                Debug::Log->info(
                    "<Menu:createLevel> Creating new Map file : '{0}'",
                    newLevelName);
                vili::ViliParser newFileParser;
                newFileParser.addFlag("Map");
                newFileParser.addFlag("Lock");
                newFileParser.includeFile("Obe");
                newFileParser->createComplexNode("Meta");
                newFileParser.at("Meta").createDataNode("name", newLevelName);
                newFileParser->createComplexNode("View");
                newFileParser.at("View").createComplexNode("pos");
                newFileParser.at("View", "pos")
                    .createDataNode("unit", "SceneUnits");
                newFileParser.at("View", "pos").createDataNode("x", 0);
                newFileParser.at("View", "pos").createDataNode("y", 0);
                newFileParser.at("View", "pos")
                    .useTemplate(
                        newFileParser.getTemplate("Vector2<SceneUnits>"));
                newFileParser.at("View").createDataNode("size", 1);
                newFileParser.writeFile(System::Path("Data/Maps")
                                            .add(newLevelName + ".map.vili")
                                            .getPath(0)
                                            .toString(),
                                        true);
                input->setText("");
            }
            else
                Debug::Log->warn("<Menu:createLevel> Map file : '{0}' already "
                                 "exists, cancelling operation",
                                 newLevelName);
        }
    }

    std::string chooseMapMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({windowSize, windowSize}, "ObEngine Map Selector",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");
        std::string currentMap;

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr bottomPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Scrollbar::Ptr scrollbar = tgui::Scrollbar::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Label::Ptr mapEditorLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Label::Ptr createMapLabel = tgui::Label::create();
        tgui::Button::Ptr createMapButton = tgui::Button::create();
        tgui::EditBox::Ptr createMapInput = tgui::EditBox::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        bottomPanel->setRenderer(baseTheme.getRenderer("Panel"));
        bottomPanel->setSize("100%", "10%");
        bottomPanel->setPosition("0", "90%");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "80%");
        middlePanel->setPosition("0", "10%");

        scrollbar->setPosition("620", "10% - 1");
        scrollbar->setSize("16", "80% + 1");
        scrollbar->connect("ValueChanged", scrollPanel, middlePanel, scrollbar);

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine");
        titleLabel->setTextSize(windowSize * 0.06);
        titleLabel->setPosition("2.5%", "15=5%");

        mapEditorLabel->setRenderer(baseTheme.getRenderer("Label"));
        mapEditorLabel->setText("<Map Editor>");
        mapEditorLabel->setTextSize(windowSize * 0.035);
        mapEditorLabel->setPosition(tgui::bindRight(titleLabel) + 20, "40%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        createMapLabel->setRenderer(baseTheme.getRenderer("Label"));
        createMapLabel->setText("Create Level : ");
        createMapLabel->setTextSize(windowSize * 0.045);
        createMapLabel->setPosition("2.5%", "20%");

        auto createMapLambda = [createMapInput, middlePanel, scrollbar,
                                &baseTheme, &currentMap]() {
            createLevel(createMapInput);
            chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);
        };

        createMapButton->setRenderer(baseTheme.getRenderer("AddButton"));
        createMapButton->setSize("height", "50%");
        createMapButton->setPosition("90%", "25%");
        createMapButton->connect("pressed", createMapLambda);

        createMapInput->setRenderer(baseTheme.getRenderer("TextBox"));
        createMapInput->setSize("47%", "50%");
        createMapInput->setPosition("35%", "25%");
        createMapInput->connect("returnkeypressed", createMapLambda);

        gui.add(topPanel);
        gui.add(bottomPanel);
        gui.add(middlePanel);
        gui.add(scrollbar);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        topPanel->add(mapEditorLabel);
        bottomPanel->add(createMapButton);
        bottomPanel->add(createMapLabel);
        bottomPanel->add(createMapInput);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);

        while (window.isOpen() && currentMap == "")
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseWheelScrolled)
                {
                    scrollbar->mouseWheelScrolled(
                        event.mouseWheelScroll.delta * 30, sf::Vector2f(0, 0));
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }

        return currentMap;
    }

    void startDevMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({ windowSize, windowSize },
            "ObEngine Development Window",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Button::Ptr playButton = tgui::Button::create();
        tgui::Button::Ptr editButton = tgui::Button::create();
        tgui::Button::Ptr toolkitButton = tgui::Button::create();
        tgui::Button::Ptr helpButton = tgui::Button::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "90%");
        middlePanel->setPosition("0", "10%");

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine Development Menu");
        titleLabel->setTextSize(float(windowSize) * 0.06);
        titleLabel->setPosition("2.5%", "15%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        auto checkBootFile = [playButton]() {
            if (System::Path("boot.lua").find() == "")
            {
                playButton->disable();
            }
            else
            {
                playButton->enable();
            }
        };

        auto checkMapFolder = [editButton]() {
            if (System::Path("Data/Maps").find(System::PathType::Directory) ==
                "")
            {
                editButton->disable();
            }
            else
            {
                editButton->enable();
            }
        };

        checkBootFile();
        checkMapFolder();

        playButton->setRenderer(baseTheme.getRenderer("PlaySquareButton"));
        playButton->setSize("50%", "50%");
        playButton->setPosition("0", "0");
        playButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            startGame();
            checkBootFile();
            checkMapFolder();
        });

        editButton->setRenderer(baseTheme.getRenderer("EditSquareButton"));
        editButton->setSize("50%", "50%");
        editButton->setPosition(tgui::bindRight(playButton), "0");
        editButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            std::string editMapName = chooseMapMenu();
            if (editMapName != "")
                Editor::editMap(editMapName);
            checkBootFile();
            checkMapFolder();
        });

        toolkitButton->setRenderer(
            baseTheme.getRenderer("ToolkitSquareButton"));
        toolkitButton->setSize("50%", "50%");
        toolkitButton->setPosition("0", tgui::bindBottom(playButton));
        toolkitButton->connect("pressed",
                               [&window, &checkBootFile, &checkMapFolder]() {
                                   startToolkitMode();
                                   checkBootFile();
                                   checkMapFolder();
                                   System::InitConfiguration();
                               });

        helpButton->setRenderer(baseTheme.getRenderer("HelpSquareButton"));
        helpButton->setSize("50%", "50%");
        helpButton->setPosition(tgui::bindLeft(editButton),
                                tgui::bindBottom(playButton));
        // helpButton->connect("pressed", [&window]()

        gui.add(topPanel);
        gui.add(middlePanel);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        middlePanel->add(playButton);
        middlePanel->add(editButton);
        middlePanel->add(toolkitButton);
        middlePanel->add(helpButton);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                    {
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                    }
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }
    }
} // namespace obe::Modes
<commit_msg>Fixed map selector<commit_after>#include <TGUI/TGUI.hpp>
#include <vili/Vili.hpp>

#include "System/Window.hpp"
#include <Editor/MapEditor.hpp>
#include <Modes/Game.hpp>
#include <Modes/Menu.hpp>
#include <Modes/Toolkit.hpp>
#include <System/Config.hpp>
#include <System/Loaders.hpp>
#include <System/Path.hpp>
#include <Utils/StringUtils.hpp>
#include <thread>

namespace obe::Modes
{
    void scrollPanel(tgui::Panel::Ptr panel, tgui::Scrollbar::Ptr scrollbar)
    {
        static int previousScrolbarValue = 0;
        const int distanceToMove =
            previousScrolbarValue - scrollbar->getValue();

        for (auto& widget : panel->getWidgets())
            widget->setPosition(widget->getPosition().x,
                                widget->getPosition().y + distanceToMove);

        previousScrolbarValue = scrollbar->getValue();
    }

    void chooseMapAddMaps(tgui::Panel::Ptr middlePanel,
                          tgui::Scrollbar::Ptr scrollbar,
                          tgui::Theme& baseTheme, std::string& currentMap)
    {
        int scrollBoxSize = 0;

        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);

        middlePanel->removeAllWidgets();

        std::vector<std::string> allMapsTemp;
        System::Path("Data/Maps")
            .loadAll(System::Loaders::filePathLoader, allMapsTemp);
        std::vector<std::string> allMaps;
        for (int i = 0; i < allMapsTemp.size(); i++)
        {
            if (Utils::String::endsWith(allMapsTemp[i], ".map.vili"))
                allMaps.push_back(allMapsTemp[i]);
        }
        for (int i = 0; i < allMaps.size(); i++)
        {
            vili::ViliParser mapInfoParser;
            mapInfoParser.setQuickLookAttributes({"Meta"});
            System::Path("Data/Maps")
                .add(allMaps[i])
                .load(System::Loaders::dataLoader, mapInfoParser);
            const std::string filename = allMaps[i];
            std::string levelName = "???";

            if (mapInfoParser->contains(vili::NodeType::ComplexNode, "Meta"))
            {
                if (mapInfoParser.at("Meta").contains(vili::NodeType::DataNode,
                                                      "name"))
                    levelName = mapInfoParser.at("Meta")
                                    .getDataNode("name")
                                    .get<std::string>();
            }

            tgui::Button::Ptr selectMapButton = tgui::Button::create();
            middlePanel->add(selectMapButton);
            selectMapButton->setText(
                levelName + " (" +
                filename.substr(0, allMapsTemp[i].size() - 9) + ")");
            selectMapButton->setRenderer(
                baseTheme.getRenderer("MapSelectButton"));
            selectMapButton->setSize("100%", "20%");
            middlePanel->add(selectMapButton);
            selectMapButton->setPosition("0", i * selectMapButton->getSize().y);
            selectMapButton->connect(
                "pressed", [&currentMap, filename] { currentMap = filename; });
            scrollBoxSize += selectMapButton->getSize().y - 1;
        }
        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);
    }

    void createLevel(tgui::EditBox::Ptr input)
    {
        const std::string newLevelName = input->getText();
        if (newLevelName != "")
        {
            if (!Utils::File::fileExists(System::Path("Data/Maps")
                                             .add(newLevelName + ".map.vili")
                                             .getPath(0)
                                             .toString()))
            {
                Debug::Log->info(
                    "<Menu:createLevel> Creating new Map file : '{0}'",
                    newLevelName);
                vili::ViliParser newFileParser;
                newFileParser.addFlag("Map");
                newFileParser.addFlag("Lock");
                newFileParser.includeFile("Obe");
                newFileParser->createComplexNode("Meta");
                newFileParser.at("Meta").createDataNode("name", newLevelName);
                newFileParser->createComplexNode("View");
                newFileParser.at("View").createComplexNode("pos");
                newFileParser.at("View", "pos")
                    .createDataNode("unit", "SceneUnits");
                newFileParser.at("View", "pos").createDataNode("x", 0);
                newFileParser.at("View", "pos").createDataNode("y", 0);
                newFileParser.at("View", "pos")
                    .useTemplate(
                        newFileParser.getTemplate("Vector2<SceneUnits>"));
                newFileParser.at("View").createDataNode("size", 1);
                newFileParser.writeFile(System::Path("Data/Maps")
                                            .add(newLevelName + ".map.vili")
                                            .getPath(0)
                                            .toString(),
                                        true);
                input->setText("");
            }
            else
                Debug::Log->warn("<Menu:createLevel> Map file : '{0}' already "
                                 "exists, cancelling operation",
                                 newLevelName);
        }
    }

    std::string chooseMapMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({windowSize, windowSize}, "ObEngine Map Selector",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");
        std::string currentMap;

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr bottomPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Scrollbar::Ptr scrollbar = tgui::Scrollbar::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Label::Ptr mapEditorLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Label::Ptr createMapLabel = tgui::Label::create();
        tgui::Button::Ptr createMapButton = tgui::Button::create();
        tgui::EditBox::Ptr createMapInput = tgui::EditBox::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        bottomPanel->setRenderer(baseTheme.getRenderer("Panel"));
        bottomPanel->setSize("100%", "10%");
        bottomPanel->setPosition("0", "90%");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "80%");
        middlePanel->setPosition("0", "10%");

        scrollbar->setPosition("620", "10% - 1");
        scrollbar->setSize("16", "80% + 1");
        scrollbar->connect("ValueChanged", scrollPanel, middlePanel, scrollbar);

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine");
        titleLabel->setTextSize(windowSize * 0.06);
        titleLabel->setPosition("2.5%", "15=5%");

        mapEditorLabel->setRenderer(baseTheme.getRenderer("Label"));
        mapEditorLabel->setText("<Map Editor>");
        mapEditorLabel->setTextSize(windowSize * 0.035);
        mapEditorLabel->setPosition(tgui::bindRight(titleLabel) + 20, "40%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        createMapLabel->setRenderer(baseTheme.getRenderer("Label"));
        createMapLabel->setText("Create Level : ");
        createMapLabel->setTextSize(windowSize * 0.045);
        createMapLabel->setPosition("2.5%", "20%");

        auto createMapLambda = [createMapInput, middlePanel, scrollbar,
                                &baseTheme, &currentMap]() {
            createLevel(createMapInput);
            chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);
        };

        createMapButton->setRenderer(baseTheme.getRenderer("AddButton"));
        createMapButton->setSize("height", "50%");
        createMapButton->setPosition("90%", "25%");
        createMapButton->connect("pressed", createMapLambda);

        createMapInput->setRenderer(baseTheme.getRenderer("TextBox"));
        createMapInput->setSize("47%", "50%");
        createMapInput->setPosition("35%", "25%");
        createMapInput->connect("returnkeypressed", createMapLambda);

        gui.add(topPanel);
        gui.add(bottomPanel);
        gui.add(middlePanel);
        gui.add(scrollbar);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        topPanel->add(mapEditorLabel);
        bottomPanel->add(createMapButton);
        bottomPanel->add(createMapLabel);
        bottomPanel->add(createMapInput);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);

        while (window.isOpen() && currentMap == "")
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseWheelScrolled)
                {
                    scrollbar->mouseWheelScrolled(
                        event.mouseWheelScroll.delta * 30, sf::Vector2f(0, 0));
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }

        return currentMap;
    }

    void startDevMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({ windowSize, windowSize },
            "ObEngine Development Window",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Button::Ptr playButton = tgui::Button::create();
        tgui::Button::Ptr editButton = tgui::Button::create();
        tgui::Button::Ptr toolkitButton = tgui::Button::create();
        tgui::Button::Ptr helpButton = tgui::Button::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "90%");
        middlePanel->setPosition("0", "10%");

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine Development Menu");
        titleLabel->setTextSize(float(windowSize) * 0.06);
        titleLabel->setPosition("2.5%", "15%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        auto checkBootFile = [playButton]() {
            if (System::Path("boot.lua").find() == "")
            {
                playButton->disable();
            }
            else
            {
                playButton->enable();
            }
        };

        auto checkMapFolder = [editButton]() {
            if (System::Path("Data/Maps").find(System::PathType::Directory) ==
                "")
            {
                editButton->disable();
            }
            else
            {
                editButton->enable();
            }
        };

        checkBootFile();
        checkMapFolder();

        playButton->setRenderer(baseTheme.getRenderer("PlaySquareButton"));
        playButton->setSize("50%", "50%");
        playButton->setPosition("0", "0");
        playButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            startGame();
            checkBootFile();
            checkMapFolder();
        });

        editButton->setRenderer(baseTheme.getRenderer("EditSquareButton"));
        editButton->setSize("50%", "50%");
        editButton->setPosition(tgui::bindRight(playButton), "0");
        editButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            std::string editMapName = chooseMapMenu();
            if (editMapName != "")
                Editor::editMap(editMapName);
            checkBootFile();
            checkMapFolder();
        });

        toolkitButton->setRenderer(
            baseTheme.getRenderer("ToolkitSquareButton"));
        toolkitButton->setSize("50%", "50%");
        toolkitButton->setPosition("0", tgui::bindBottom(playButton));
        toolkitButton->connect("pressed",
                               [&window, &checkBootFile, &checkMapFolder]() {
                                   startToolkitMode();
                                   checkBootFile();
                                   checkMapFolder();
                                   System::InitConfiguration();
                               });

        helpButton->setRenderer(baseTheme.getRenderer("HelpSquareButton"));
        helpButton->setSize("50%", "50%");
        helpButton->setPosition(tgui::bindLeft(editButton),
                                tgui::bindBottom(playButton));
        // helpButton->connect("pressed", [&window]()

        gui.add(topPanel);
        gui.add(middlePanel);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        middlePanel->add(playButton);
        middlePanel->add(editButton);
        middlePanel->add(toolkitButton);
        middlePanel->add(helpButton);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                    {
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                    }
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }
    }
} // namespace obe::Modes
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#include <QApplication>
#include <QDesktopServices>
#include <QString>
#include <QTcpSocket>
#include <QVariantMap>
#include <QNetworkInterface>
#include "de_web_plugin.h"
#include "de_web_plugin_private.h"
#include "json.h"
#include <stdlib.h>

/*! Configuration REST API broker.
    \param req - request data
    \param rsp - response data
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::handleUserparameterApi(const ApiRequest &req, ApiResponse &rsp)
{
    if (req.path[2] != QLatin1String("userparameter"))
    {
        return REQ_NOT_HANDLED;
    }

    // POST /api/<apikey>/userparameter/
    if ((req.path.size() == 3) && (req.hdr.method() == "POST"))
    {
        return createUserParameter(req, rsp);
    }
    // POST /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "POST"))
    {
        return addUserParameter(req, rsp);
    }
    // PUT /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "PUT"))
    {
        return modifyUserParameter(req, rsp);
    }
    // GET /api/<apikey>/userparameter
    else if ((req.path.size() == 3) && (req.hdr.method() == "GET"))
    {
        return getAllUserParameter(req, rsp);
    }
    // GET /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "GET"))
    {
        return getUserParameter(req, rsp);
    }
    // DELETE /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "DELETE"))
    {
        return deleteUserParameter(req, rsp);
    }
    return REQ_NOT_HANDLED;
}

/*! POST /api/<apikey>/userparameter
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::createUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    if (req.content.isEmpty())
    {
        rsp.list.append(errorToMap(ERR_INVALID_VALUE, QString("/userparameter"), QString("invalid value for userparameter")));
        rsp.httpStatus = HttpStatusBadRequest;
        return REQ_READY_SEND;
    }

    rsp.httpStatus = HttpStatusOk;

    // generate id
    int i = 1;
    while (gwUserParameter.contains(QString::number(i)))
    {
        i++;
    }

    QString id = QString::number(i);

    QVariantMap rspItem;
    QVariantMap rspItemState;

    gwUserParameter.insert(id, req.content);
    rspItemState["id"] = id;
    rspItem["success"] = rspItemState;
    rsp.list.append(rspItem);

    queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    return REQ_READY_SEND;
}

/*! POST /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::addUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    rsp.httpStatus = HttpStatusOk;

    //don't overwrite existing parameters if POST request
    if (gwUserParameter.contains(key))
    {
        rsp.httpStatus = HttpStatusBadRequest;
        rsp.list.append(errorToMap(ERR_DUPLICATE_EXIST ,
        QString("config/userparameter"), QString("key %1 already exists").arg(key)));
        return REQ_READY_SEND;
    }

    QVariantMap rspItem;
    QVariantMap rspItemState;

    gwUserParameter.insert(key, req.content);
    rspItemState["/config/userparameter"] = QString("added new %1").arg(key);
    rspItem["success"] = rspItemState;
    rsp.list.append(rspItem);

    queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    return REQ_READY_SEND;
}

/*! PUT /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::modifyUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    rsp.httpStatus = HttpStatusOk;

    QVariantMap rspItem;
    QVariantMap rspItemState;

    //overwrite existing parameters if PUT request
    if (gwUserParameter.contains(key))
    {
        QVariantMap::iterator it = gwUserParameter.find(key);

        if (*it != req.content)
        {
            gwUserParameter.erase(it);
            gwUserParameter.insert(key, req.content);
            queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
        }

        rspItemState["/config/userparameter"] = QString("updated %1").arg(key);
        rspItem["success"] = rspItemState;
        rsp.list.append(rspItem);
    }
    else
    {
        gwUserParameter.insert(key, req.content);
        rspItemState["/config/userparameter"] = QString("added new %1").arg(key);
        rspItem["success"] = rspItemState;
        rsp.list.append(rspItem);
        queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    }

    return REQ_READY_SEND;
}

/*! GET /api/<apikey>/userparameter
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::getAllUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    Q_UNUSED(req);

    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    rsp.httpStatus = HttpStatusOk;

    QVariantMap::const_iterator k = gwUserParameter.begin();
    QVariantMap::const_iterator kend = gwUserParameter.end();

    for (; k != kend; ++k)
    {
        rsp.map[k.key()] = gwUserParameter.value(k.key());
    }

    if (rsp.map.isEmpty())
    {
        rsp.str = "{}"; // return empty object
    }

    return REQ_READY_SEND;
}

/*! GET /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::getUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    Q_UNUSED(req);

    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    rsp.httpStatus = HttpStatusOk;

    if (gwUserParameter.contains(key))
    {
        rsp.map[key] =  gwUserParameter.value(key);
    }
    else
    {
        QVariantMap rspItem;
        QVariantMap rspItemState;
        rspItemState["/config/userparameter"] = QString("key %1 not found").arg(key);
        rspItem["error"] = rspItemState;
        rsp.list.append(rspItem);
        rsp.httpStatus = HttpStatusNotFound;
    }

    return REQ_READY_SEND;
}

/*! DELETE /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::deleteUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    QVariantMap rspItem;
    QVariantMap rspItemState;

    if (gwUserParameter.contains(key))
    {
        gwUserParameter.remove(key);
        gwUserParameterToDelete.push_back(key);
        rspItemState["/config/userparameter"] = QString("key %1 removed").arg(key);
        rspItem["success"] = rspItemState;
        rsp.list.append(rspItem);
        rsp.httpStatus = HttpStatusOk;
        queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    }
    else
    {
        rspItemState["/config/userparameter"] = QString("key %1 not found").arg(key);
        rspItem["error"] = rspItemState;
        rsp.list.append(rspItem);
        rsp.httpStatus = HttpStatusNotFound;
    }

    return REQ_READY_SEND;
}
<commit_msg>Support PATCH method for userparameters<commit_after>/*
 * Copyright (c) 2016 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#include <QApplication>
#include <QDesktopServices>
#include <QString>
#include <QTcpSocket>
#include <QVariantMap>
#include <QNetworkInterface>
#include "de_web_plugin.h"
#include "de_web_plugin_private.h"
#include "json.h"
#include <stdlib.h>

/*! Configuration REST API broker.
    \param req - request data
    \param rsp - response data
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::handleUserparameterApi(const ApiRequest &req, ApiResponse &rsp)
{
    if (req.path[2] != QLatin1String("userparameter"))
    {
        return REQ_NOT_HANDLED;
    }

    // POST /api/<apikey>/userparameter/
    if ((req.path.size() == 3) && (req.hdr.method() == "POST"))
    {
        return createUserParameter(req, rsp);
    }
    // POST /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "POST"))
    {
        return addUserParameter(req, rsp);
    }
    // PUT /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "PUT" || req.hdr.method() == "PATCH"))
    {
        return modifyUserParameter(req, rsp);
    }
    // GET /api/<apikey>/userparameter
    else if ((req.path.size() == 3) && (req.hdr.method() == "GET"))
    {
        return getAllUserParameter(req, rsp);
    }
    // GET /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "GET"))
    {
        return getUserParameter(req, rsp);
    }
    // DELETE /api/<apikey>/userparameter/<parameter>
    else if ((req.path.size() == 4) && (req.hdr.method() == "DELETE"))
    {
        return deleteUserParameter(req, rsp);
    }
    return REQ_NOT_HANDLED;
}

/*! POST /api/<apikey>/userparameter
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::createUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    if (req.content.isEmpty())
    {
        rsp.list.append(errorToMap(ERR_INVALID_VALUE, QString("/userparameter"), QString("invalid value for userparameter")));
        rsp.httpStatus = HttpStatusBadRequest;
        return REQ_READY_SEND;
    }

    rsp.httpStatus = HttpStatusOk;

    // generate id
    int i = 1;
    while (gwUserParameter.contains(QString::number(i)))
    {
        i++;
    }

    QString id = QString::number(i);

    QVariantMap rspItem;
    QVariantMap rspItemState;

    gwUserParameter.insert(id, req.content);
    rspItemState["id"] = id;
    rspItem["success"] = rspItemState;
    rsp.list.append(rspItem);

    queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    return REQ_READY_SEND;
}

/*! POST /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::addUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    rsp.httpStatus = HttpStatusOk;

    //don't overwrite existing parameters if POST request
    if (gwUserParameter.contains(key))
    {
        rsp.httpStatus = HttpStatusBadRequest;
        rsp.list.append(errorToMap(ERR_DUPLICATE_EXIST ,
        QString("config/userparameter"), QString("key %1 already exists").arg(key)));
        return REQ_READY_SEND;
    }

    QVariantMap rspItem;
    QVariantMap rspItemState;

    gwUserParameter.insert(key, req.content);
    rspItemState["/config/userparameter"] = QString("added new %1").arg(key);
    rspItem["success"] = rspItemState;
    rsp.list.append(rspItem);

    queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    return REQ_READY_SEND;
}

/*! PUT /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::modifyUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    rsp.httpStatus = HttpStatusOk;

    QVariantMap rspItem;
    QVariantMap rspItemState;

    //overwrite existing parameters if PUT request
    if (gwUserParameter.contains(key))
    {
        QVariantMap::iterator it = gwUserParameter.find(key);

        if (*it != req.content)
        {
            gwUserParameter.erase(it);
            gwUserParameter.insert(key, req.content);
            queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
        }

        rspItemState["/config/userparameter"] = QString("updated %1").arg(key);
        rspItem["success"] = rspItemState;
        rsp.list.append(rspItem);
    }
    else
    {
        gwUserParameter.insert(key, req.content);
        rspItemState["/config/userparameter"] = QString("added new %1").arg(key);
        rspItem["success"] = rspItemState;
        rsp.list.append(rspItem);
        queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    }

    return REQ_READY_SEND;
}

/*! GET /api/<apikey>/userparameter
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::getAllUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    Q_UNUSED(req);

    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    rsp.httpStatus = HttpStatusOk;

    QVariantMap::const_iterator k = gwUserParameter.begin();
    QVariantMap::const_iterator kend = gwUserParameter.end();

    for (; k != kend; ++k)
    {
        rsp.map[k.key()] = gwUserParameter.value(k.key());
    }

    if (rsp.map.isEmpty())
    {
        rsp.str = "{}"; // return empty object
    }

    return REQ_READY_SEND;
}

/*! GET /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::getUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    Q_UNUSED(req);

    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    rsp.httpStatus = HttpStatusOk;

    if (gwUserParameter.contains(key))
    {
        rsp.map[key] =  gwUserParameter.value(key);
    }
    else
    {
        QVariantMap rspItem;
        QVariantMap rspItemState;
        rspItemState["/config/userparameter"] = QString("key %1 not found").arg(key);
        rspItem["error"] = rspItemState;
        rsp.list.append(rspItem);
        rsp.httpStatus = HttpStatusNotFound;
    }

    return REQ_READY_SEND;
}

/*! DELETE /api/<apikey>/userparameter/<parameter>
    \return REQ_READY_SEND
            REQ_NOT_HANDLED
 */
int DeRestPluginPrivate::deleteUserParameter(const ApiRequest &req, ApiResponse &rsp)
{
    if(!checkApikeyAuthentification(req, rsp))
    {
        return REQ_READY_SEND;
    }

    DBG_Assert(req.path.size() == 4);

    if (req.path.size() != 4)
    {
        return -1;
    }

    const QString &key = req.path[3];

    QVariantMap rspItem;
    QVariantMap rspItemState;

    if (gwUserParameter.contains(key))
    {
        gwUserParameter.remove(key);
        gwUserParameterToDelete.push_back(key);
        rspItemState["/config/userparameter"] = QString("key %1 removed").arg(key);
        rspItem["success"] = rspItemState;
        rsp.list.append(rspItem);
        rsp.httpStatus = HttpStatusOk;
        queSaveDb(DB_USERPARAM, DB_SHORT_SAVE_DELAY);
    }
    else
    {
        rspItemState["/config/userparameter"] = QString("key %1 not found").arg(key);
        rspItem["error"] = rspItemState;
        rsp.list.append(rspItem);
        rsp.httpStatus = HttpStatusNotFound;
    }

    return REQ_READY_SEND;
}
<|endoftext|>


<commit_before>#ifndef WIN32

#pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"

#include <string>
#include <catch.hpp>

#include "chemfiles.hpp"
#include "chemfiles/TrajectoryFactory.hpp"
#include "chemfiles/Error.hpp"
#include "chemfiles/formats/XYZ.hpp"

#include "chemfiles/Frame.hpp"
using namespace chemfiles;

// Dummy format clase
class DummyFormat : public Format {
public:
    DummyFormat(File& file) : Format(file){}
    std::string description() const override {return "";}
    size_t nsteps() override {return 42;}
};

// Dummy file clase
class DummyFile : public BinaryFile {
public:
    DummyFile(const std::string&, File::Mode) : BinaryFile("", File::READ) {}
    bool is_open() override {return true;}
    void sync() override {}
};
class DummyFormat2 : public Format {
public:
    DummyFormat2(File& file) : Format(file){}
    std::string description() const override {return "";}
    size_t nsteps() override {return 42;}
    using file_t = DummyFile;
};

TEST_CASE("Registering a new format", "[Trajectory factory]"){
    TrajectoryFactory::get().register_extension(".testing", {nullptr, nullptr});
    // We can not register the same format twice
    CHECK_THROWS_AS(
        TrajectoryFactory::get().register_extension(".testing", {nullptr, nullptr}),
        FormatError
    );

    TrajectoryFactory::get().register_format("Testing", {nullptr, nullptr});
    // We can not register the same format twice
    CHECK_THROWS_AS(
        TrajectoryFactory::get().register_format("Testing", {nullptr, nullptr}),
        FormatError
    );
}

TEST_CASE("Geting registered format", "[Trajectory factory]"){
    TrajectoryFactory::get().register_extension(".dummy", {new_format<DummyFormat>, new_file<typename DummyFormat::file_t>});
    TrajectoryFactory::get().register_format("Dummy", {new_format<DummyFormat>, new_file<typename DummyFormat::file_t>});

    BasicFile file("tmp.dat", File::WRITE);

    DummyFormat dummy(file);
    auto format = TrajectoryFactory::get().by_extension(".dummy").format_creator(file);
    CHECK(typeid(dummy) == typeid(*format));
    format = TrajectoryFactory::get().format("Dummy").format_creator(file);
    CHECK(typeid(dummy) == typeid(*format));

    XYZFormat XYZ(file);
    format = TrajectoryFactory::get().by_extension(".xyz").format_creator(file);
    CHECK(typeid(XYZ) == typeid(*format));
    format = TrajectoryFactory::get().format("XYZ").format_creator(file);
    CHECK(typeid(XYZ) == typeid(*format));

    CHECK_THROWS_AS(TrajectoryFactory::get().format("UNKOWN"), FormatError);
    CHECK_THROWS_AS(TrajectoryFactory::get().by_extension(".UNKOWN"), FormatError);
}

TEST_CASE("Geting file type associated to a format", "[Trajectory factory]"){
    TrajectoryFactory::get().register_extension(".dummy2", {new_format<DummyFormat2>, new_file<typename DummyFormat2::file_t>});
    DummyFile dummy("", File::READ);
    auto file = TrajectoryFactory::get().by_extension(".dummy2").file_creator;
    CHECK(typeid(dummy) == typeid(*file("", File::READ)));
}

TEST_CASE("Check error throwing in formats", "[Format errors]"){
    // Create a dummy file
    std::string filename = "test-file.dummy";
    std::ofstream out(filename);
    out << "hey !" << std::endl;
    out.close();

    Frame frame;
    Trajectory traj(filename, 'a');
    CHECK_THROWS_AS(traj.read(), FormatError);
    CHECK_THROWS_AS(traj.read_step(2), FormatError);
    CHECK_THROWS_AS(traj.write(frame), FormatError);

    remove(filename.c_str());
}

#endif
<commit_msg>Don't ignore the factory test on WIN32<commit_after>#pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"

#include <string>
#include <catch.hpp>

#include "chemfiles.hpp"
#include "chemfiles/TrajectoryFactory.hpp"
#include "chemfiles/Error.hpp"
#include "chemfiles/formats/XYZ.hpp"

#include "chemfiles/Frame.hpp"
using namespace chemfiles;

// Dummy format clase
class DummyFormat : public Format {
public:
    DummyFormat(File& file) : Format(file){}
    std::string description() const override {return "";}
    size_t nsteps() override {return 42;}
};

// Dummy file clase
class DummyFile : public BinaryFile {
public:
    DummyFile(const std::string&, File::Mode) : BinaryFile("", File::READ) {}
    bool is_open() override {return true;}
    void sync() override {}
};
class DummyFormat2 : public Format {
public:
    DummyFormat2(File& file) : Format(file){}
    std::string description() const override {return "";}
    size_t nsteps() override {return 42;}
    using file_t = DummyFile;
};

TEST_CASE("Registering a new format", "[Trajectory factory]"){
    TrajectoryFactory::get().register_extension(".testing", {nullptr, nullptr});
    // We can not register the same format twice
    CHECK_THROWS_AS(
        TrajectoryFactory::get().register_extension(".testing", {nullptr, nullptr}),
        FormatError
    );

    TrajectoryFactory::get().register_format("Testing", {nullptr, nullptr});
    // We can not register the same format twice
    CHECK_THROWS_AS(
        TrajectoryFactory::get().register_format("Testing", {nullptr, nullptr}),
        FormatError
    );
}

TEST_CASE("Geting registered format", "[Trajectory factory]"){
    TrajectoryFactory::get().register_extension(".dummy", {new_format<DummyFormat>, new_file<typename DummyFormat::file_t>});
    TrajectoryFactory::get().register_format("Dummy", {new_format<DummyFormat>, new_file<typename DummyFormat::file_t>});

    BasicFile file("tmp.dat", File::WRITE);

    DummyFormat dummy(file);
    auto format = TrajectoryFactory::get().by_extension(".dummy").format_creator(file);
    CHECK(typeid(dummy) == typeid(*format));
    format = TrajectoryFactory::get().format("Dummy").format_creator(file);
    CHECK(typeid(dummy) == typeid(*format));

    XYZFormat XYZ(file);
    format = TrajectoryFactory::get().by_extension(".xyz").format_creator(file);
    CHECK(typeid(XYZ) == typeid(*format));
    format = TrajectoryFactory::get().format("XYZ").format_creator(file);
    CHECK(typeid(XYZ) == typeid(*format));

    CHECK_THROWS_AS(TrajectoryFactory::get().format("UNKOWN"), FormatError);
    CHECK_THROWS_AS(TrajectoryFactory::get().by_extension(".UNKOWN"), FormatError);
}

TEST_CASE("Geting file type associated to a format", "[Trajectory factory]"){
    TrajectoryFactory::get().register_extension(".dummy2", {new_format<DummyFormat2>, new_file<typename DummyFormat2::file_t>});
    DummyFile dummy("", File::READ);
    auto file = TrajectoryFactory::get().by_extension(".dummy2").file_creator;
    CHECK(typeid(dummy) == typeid(*file("", File::READ)));
}

TEST_CASE("Check error throwing in formats", "[Format errors]"){
    // Create a dummy file
    std::string filename = "test-file.dummy";
    std::ofstream out(filename);
    out << "hey !" << std::endl;
    out.close();

    Frame frame;
    Trajectory traj(filename, 'a');
    CHECK_THROWS_AS(traj.read(), FormatError);
    CHECK_THROWS_AS(traj.read_step(2), FormatError);
    CHECK_THROWS_AS(traj.write(frame), FormatError);

    remove(filename.c_str());
}
<|endoftext|>


<commit_before>//
//  rule.cpp
//  Parse
//
//  Created by Andrew Hunter on 30/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "rule.h"
#include "standard_items.h"

using namespace contextfree;

/// \brief Creates a copy of a rule
rule::rule(const rule& copyFrom)
: m_NonTerminal(copyFrom.m_NonTerminal)
, m_Items(copyFrom.m_Items) {
}

/// \brief Creates a copy of a rule with an alternative nonterminal
rule::rule(const rule& copyFrom, const item_container& nonTerminal)
: m_NonTerminal(nonTerminal)
, m_Items(copyFrom.m_Items) {
}

/// \brief Creates an empty rule, which reduces to the specified item
rule::rule(const item_container& nonTerminal)
: m_NonTerminal(nonTerminal) {
}

/// \brief Creates an empty rule with a nonterminal identifier
rule::rule(const int nonTerminal) {
    contextfree::nonterminal nt(nonTerminal);
    m_NonTerminal = item_container(nt);
}

/// \brief Copies the content of a rule into this one
rule& rule::operator=(const rule& copyFrom) {
    m_NonTerminal   = copyFrom.m_NonTerminal;
    m_Items         = copyFrom.m_Items;

    return *this;
}

/// \brief Orders this rule relative to another
bool rule::operator<(const rule& compareTo) const {
    // Number of items is the fastest thing to compare, so check that first
    if (m_Items.size() < compareTo.m_Items.size())  return true;
    if (m_Items.size() > compareTo.m_Items.size())  return false;

    // The nonterminal should be reasonably fast to compare
    if (m_NonTerminal < compareTo.m_NonTerminal)    return true;

    // Need to compare each item in turn
    item_list::const_iterator ourItem   = m_Items.begin();
    item_list::const_iterator theirItem = compareTo.begin();

    for (;ourItem != m_Items.end() && theirItem != compareTo.end(); ourItem++, theirItem++) {
        if (*ourItem < *theirItem) return true;
    }

    return false;
}

/// \brief Determines if this rule is the same as another
bool rule::operator==(const rule& compareTo) const {
    // Number of items is the fastest thing to compare, so check that first
    if (m_Items.size() != compareTo.m_Items.size()) return false;

    // The nonterminal should be reasonably fast to compare
    if (m_NonTerminal != compareTo.m_NonTerminal)   return false;

    // Need to compare each item in turn
    item_list::const_iterator ourItem   = m_Items.begin();
    item_list::const_iterator theirItem = compareTo.begin();

    for (;ourItem != m_Items.end() && theirItem != compareTo.end(); ourItem++, theirItem++) {
        if (*ourItem != *theirItem) return false;
    }

    return true;
}

/// \brief Appends the specified item to this rule
rule& rule::operator<<(const item_container& item) {
    // Add this item to the list of items
    m_Items.push_back(item);

    return *this;
}
<commit_msg>Added a method for retrieving the identifier of a rule (with caching for perfomance)<commit_after>//
//  rule.cpp
//  Parse
//
//  Created by Andrew Hunter on 30/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "rule.h"
#include "standard_items.h"

using namespace contextfree;

/// \brief Creates a copy of a rule
rule::rule(const rule& copyFrom)
: m_NonTerminal(copyFrom.m_NonTerminal)
, m_Items(copyFrom.m_Items) {
}

/// \brief Creates a copy of a rule with an alternative nonterminal
rule::rule(const rule& copyFrom, const item_container& nonTerminal)
: m_NonTerminal(nonTerminal)
, m_Items(copyFrom.m_Items) {
}

/// \brief Creates an empty rule, which reduces to the specified item
rule::rule(const item_container& nonTerminal)
: m_NonTerminal(nonTerminal) {
}

/// \brief Creates an empty rule with a nonterminal identifier
rule::rule(const int nonTerminal) {
    contextfree::nonterminal nt(nonTerminal);
    m_NonTerminal = item_container(nt);
}

/// \brief Copies the content of a rule into this one
rule& rule::operator=(const rule& copyFrom) {
    m_NonTerminal   = copyFrom.m_NonTerminal;
    m_Items         = copyFrom.m_Items;

    return *this;
}

/// \brief Orders this rule relative to another
bool rule::operator<(const rule& compareTo) const {
    // Number of items is the fastest thing to compare, so check that first
    if (m_Items.size() < compareTo.m_Items.size())  return true;
    if (m_Items.size() > compareTo.m_Items.size())  return false;

    // The nonterminal should be reasonably fast to compare
    if (m_NonTerminal < compareTo.m_NonTerminal)    return true;

    // Need to compare each item in turn
    item_list::const_iterator ourItem   = m_Items.begin();
    item_list::const_iterator theirItem = compareTo.begin();

    for (;ourItem != m_Items.end() && theirItem != compareTo.end(); ourItem++, theirItem++) {
        if (*ourItem < *theirItem) return true;
    }

    return false;
}

/// \brief Determines if this rule is the same as another
bool rule::operator==(const rule& compareTo) const {
    // Number of items is the fastest thing to compare, so check that first
    if (m_Items.size() != compareTo.m_Items.size()) return false;

    // The nonterminal should be reasonably fast to compare
    if (m_NonTerminal != compareTo.m_NonTerminal)   return false;

    // Need to compare each item in turn
    item_list::const_iterator ourItem   = m_Items.begin();
    item_list::const_iterator theirItem = compareTo.begin();

    for (;ourItem != m_Items.end() && theirItem != compareTo.end(); ourItem++, theirItem++) {
        if (*ourItem != *theirItem) return false;
    }

    return true;
}

/// \brief Appends the specified item to this rule
rule& rule::operator<<(const item_container& item) {
    // Add this item to the list of items
    m_Items.push_back(item);

    return *this;
}

/// \brief Returns the identifier for this rule in the specified grammar
int rule::identifier(const grammar& gram) const {
    if (&gram == m_LastGrammar) return m_Identifier;

    m_LastGrammar = &gram;
    return m_Identifier = gram.identifier_for_rule(*this);
}
<|endoftext|>


<commit_before>/*
  JcMess: A simple utility so save your jack-audio mess.

  Copyright (C) 2007-2010 Juan-Pablo Caceres.

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

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

/*
 * jcmess.cpp
 */

#include "jcmess.h"

#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <sys/stat.h>

#define SEPARATOR " -#- "

//-------------------------------------------------------------------------------
/*! \brief Constructs a JcMess object that has a jack client.
 *
 */
//-------------------------------------------------------------------------------
JcMess::JcMess()
{
  //Open a client connection to the JACK server.  Starting a
  //new server only to list its ports seems pointless, so we
  //specify JackNoStartServer.
  mClient = jack_client_open ("lsp", JackNoStartServer, &mStatus);
  if (mClient == NULL) {
    if (mStatus & JackServerFailed) {
      cerr << "JACK server not running" << endl;
    } else {
      cerr << "jack_client_open() failed, "
	   << "status = 0x%2.0x\n" << mStatus << endl;
    }
    exit(1);
  }
}

//-------------------------------------------------------------------------------
/*! \brief Distructor closes the jcmess jack audio client.
 *
 */
//-------------------------------------------------------------------------------
JcMess::~JcMess()
{
  if (jack_client_close(mClient))
    cerr << "ERROR: Could not close the hidden jcmess jack client." << endl;
}

//-------------------------------------------------------------------------------
/*! \brief Write an XML file with the name specified at OutFile.
 *
 */
//-------------------------------------------------------------------------------

// Function: fileExists
/**
    Check if a file exists
@param[in] filename - the name of the file to check

@return    true if the file exists, else false

*/
bool fileExists(const std::string& filename)
{
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
    {
        return true;
    }
    return false;
}

void JcMess::writeOutput(string OutFile)
{
  stringstream ss;
  vector<string> OutputInput(2);

  this->setConnectedPorts();

  for (vector<vector<string> >::iterator it = mConnectedPorts.begin(); it != mConnectedPorts.end(); ++it) {
    OutputInput = *it;
    //cout << "Output ===> " << OutputInput[0] << endl;
    //cout << "Input ===> " << OutputInput[1] << endl;
    cout << OutputInput[0] << SEPARATOR << OutputInput[1] << endl;
    ss << OutputInput[0] << SEPARATOR << OutputInput[1] << endl;

  }

  ofstream file;
  file.clear(file.failbit);
  file.clear(file.badbit);

  //Write output file
  string answer = "";
  //Check for existing file first, and confirm before overwriting
  if (fileExists(OutFile)) {
    while ((answer != "yes") && (answer != "no")) {
      cout << "WARNING: The File " << OutFile
	   << " exists. Do you want to overwrite it? (yes/no): ";
      cin >> answer;
    }
  }
  else {
    answer = "yes";
  }

  if (answer == "yes") {
    //file.open(OutFile.c_str(),fstream::out);
    file.open(OutFile.c_str());
    if (file.fail()) {
      cerr << "Cannot open file for writing: " << endl;
      exit(1);
    }

    //TODO save the file
    file << ss.rdbuf();
    file.close();
    cout << OutFile << " written." << endl;
  }
}

//-------------------------------------------------------------------------------
/*! \brief Set list of ouput ports that have connections.
 *
 */
//-------------------------------------------------------------------------------
void JcMess::setConnectedPorts()
{
  mConnectedPorts.clear();

  const char **ports, **connections; //vector of ports and connections
  vector<string> OutputInput(2); //helper variable

  //Get active output ports.
  ports = jack_get_ports (mClient, NULL, NULL, JackPortIsOutput);

  for (unsigned int out_i = 0; ports[out_i]; ++out_i) {
    if ((connections = jack_port_get_all_connections
	 (mClient, jack_port_by_name(mClient, ports[out_i]))) != 0) {
      for (unsigned int in_i = 0; connections[in_i]; ++in_i) {
	OutputInput[0] = ports[out_i];
	//cout << "Output ===> " << OutputInput[0] << endl;
	OutputInput[1] = connections[in_i];
	//cout << "Input ===> " << OutputInput[1] << endl;
	mConnectedPorts.push_back(OutputInput);
      }
    }
  }

  free(ports);
}

//-------------------------------------------------------------------------------
/*! \brief Disconnect all the clients.
 *
 */
//-------------------------------------------------------------------------------
void JcMess::disconnectAll()
{
  vector<string> OutputInput(2);

  this->setConnectedPorts();

  for (vector<vector<string> >::iterator it = mConnectedPorts.begin();
       it != mConnectedPorts.end(); ++it) {
    OutputInput = *it;

    if (jack_disconnect(mClient, OutputInput[0].c_str(), OutputInput[1].c_str())) {
      cerr << "WARNING! port| " << OutputInput[0]
	   << " |and port| " << OutputInput[1]
	   << " |could not be disconnected.\n";
    }
  }

}

//-------------------------------------------------------------------------------
/*! \brief Parse the XML input file.
 *
 * Returns 0 on success, or 1 if the file has an incorrect format or cannot
 * read the file.
 */
//-------------------------------------------------------------------------------
int JcMess::parseTextFile(string InFile)
{
  mPortsToConnect.clear();
  string errorStr;

  ifstream file;
  file.clear(file.failbit);
  file.clear(file.badbit);

  file.open(InFile.c_str());
  if (file.fail()) {
    cerr << "Cannot open file for reading: " << endl;
    return 1;
  }

  vector<string> OutputInput(2);
  const string delimiter = SEPARATOR ;

  while (!file.eof()) {
    string line;
    getline(file,line);

    size_t pos = 0;
    pos = line.find(delimiter);
    OutputInput[0] = line.substr(0, pos);
    cout << OutputInput[0] << endl;
    line.erase(0, pos + delimiter.length());
    OutputInput[1] = line ;
    mPortsToConnect.push_back(OutputInput);
  }

  file.close();

  return 0;

}

//-------------------------------------------------------------------------------
/*! \brief Connect ports specified in input XML file InFile
 *
 */
//-------------------------------------------------------------------------------
void JcMess::connectPorts(string InFile)
{
  vector<string> OutputInput(2);

  if ( !(this->parseTextFile(InFile)) ) {
    for (vector<vector<string> >::iterator it = mPortsToConnect.begin();
	 it != mPortsToConnect.end(); ++it) {
      OutputInput = *it;

      if (jack_connect(mClient, OutputInput[0].c_str(), OutputInput[1].c_str())) {
	//Display a warining only if the error is not because the ports are already
	//connected, in case the program doesn't display anyting.
	if (EEXIST !=
	    jack_connect(mClient, OutputInput[0].c_str(), OutputInput[1].c_str())) {
	  cerr << "WARNING: port: " << OutputInput[0]
	       << "and port: " << OutputInput[1]
	       << " could not be connected.\n";
	}
      }
    }
  }

}
<commit_msg>tested basic functionality for save/load jcmess file, will have to port other changes i have carried out from jmess 1.0.2.<commit_after>/*
  JcMess: A simple utility so save your jack-audio mess.

  Copyright (C) 2007-2010 Juan-Pablo Caceres.

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

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

/*
 * jcmess.cpp
 */

#include "jcmess.h"

#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <sys/stat.h>

#define SEPARATOR " -#- "

//-------------------------------------------------------------------------------
/*! \brief Constructs a JcMess object that has a jack client.
 *
 */
//-------------------------------------------------------------------------------
JcMess::JcMess()
{
  //Open a client connection to the JACK server.  Starting a
  //new server only to list its ports seems pointless, so we
  //specify JackNoStartServer.
  mClient = jack_client_open ("lsp", JackNoStartServer, &mStatus);
  if (mClient == NULL) {
    if (mStatus & JackServerFailed) {
      cerr << "JACK server not running" << endl;
    } else {
      cerr << "jack_client_open() failed, "
	   << "status = 0x%2.0x\n" << mStatus << endl;
    }
    exit(1);
  }
}

//-------------------------------------------------------------------------------
/*! \brief Distructor closes the jcmess jack audio client.
 *
 */
//-------------------------------------------------------------------------------
JcMess::~JcMess()
{
  if (jack_client_close(mClient))
    cerr << "ERROR: Could not close the hidden jcmess jack client." << endl;
}

//-------------------------------------------------------------------------------
/*! \brief Write an XML file with the name specified at OutFile.
 *
 */
//-------------------------------------------------------------------------------

// Function: fileExists
/**
    Check if a file exists
@param[in] filename - the name of the file to check

@return    true if the file exists, else false

*/
bool fileExists(const std::string& filename)
{
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
    {
        return true;
    }
    return false;
}

void JcMess::writeOutput(string OutFile)
{
  stringstream ss;
  vector<string> OutputInput(2);

  this->setConnectedPorts();

  for (vector<vector<string> >::iterator it = mConnectedPorts.begin(); it != mConnectedPorts.end(); ++it) {
    OutputInput = *it;
    //cout << "Output ===> " << OutputInput[0] << endl;
    //cout << "Input ===> " << OutputInput[1] << endl;
    cout << OutputInput[0] << SEPARATOR << OutputInput[1] << endl;
    ss << OutputInput[0] << SEPARATOR << OutputInput[1] << endl;

  }

  ofstream file;
  file.clear(file.failbit);
  file.clear(file.badbit);

  //Write output file
  string answer = "";
  //Check for existing file first, and confirm before overwriting
  if (fileExists(OutFile)) {
    while ((answer != "yes") && (answer != "no")) {
      cout << "WARNING: The File " << OutFile
	   << " exists. Do you want to overwrite it? (yes/no): ";
      cin >> answer;
    }
  }
  else {
    answer = "yes";
  }

  if (answer == "yes") {
    //file.open(OutFile.c_str(),fstream::out);
    file.open(OutFile.c_str());
    if (file.fail()) {
      cerr << "Cannot open file for writing: " << endl;
      exit(1);
    }

    file << ss.rdbuf();
    file.close();
    cout << OutFile << " written." << endl;
  }
}

//-------------------------------------------------------------------------------
/*! \brief Set list of ouput ports that have connections.
 *
 */
//-------------------------------------------------------------------------------
void JcMess::setConnectedPorts()
{
  mConnectedPorts.clear();

  const char **ports, **connections; //vector of ports and connections
  vector<string> OutputInput(2); //helper variable

  //Get active output ports.
  ports = jack_get_ports (mClient, NULL, NULL, JackPortIsOutput);

  for (unsigned int out_i = 0; ports[out_i]; ++out_i) {
    if ((connections = jack_port_get_all_connections
	 (mClient, jack_port_by_name(mClient, ports[out_i]))) != 0) {
      for (unsigned int in_i = 0; connections[in_i]; ++in_i) {
	OutputInput[0] = ports[out_i];
	//cout << "Output ===> " << OutputInput[0] << endl;
	OutputInput[1] = connections[in_i];
	//cout << "Input ===> " << OutputInput[1] << endl;
	mConnectedPorts.push_back(OutputInput);
      }
    }
  }

  free(ports);
}

//-------------------------------------------------------------------------------
/*! \brief Disconnect all the clients.
 *
 */
//-------------------------------------------------------------------------------
void JcMess::disconnectAll()
{
  vector<string> OutputInput(2);

  this->setConnectedPorts();

  for (vector<vector<string> >::iterator it = mConnectedPorts.begin();
       it != mConnectedPorts.end(); ++it) {
    OutputInput = *it;

    if (jack_disconnect(mClient, OutputInput[0].c_str(), OutputInput[1].c_str())) {
      cerr << "WARNING! port| " << OutputInput[0]
	   << " |and port| " << OutputInput[1]
	   << " |could not be disconnected.\n";
    }
  }

}

//-------------------------------------------------------------------------------
/*! \brief Parse the XML input file.
 *
 * Returns 0 on success, or 1 if the file has an incorrect format or cannot
 * read the file.
 */
//-------------------------------------------------------------------------------
int JcMess::parseTextFile(string InFile)
{
  mPortsToConnect.clear();
  string errorStr;

  ifstream file;
  file.clear(file.failbit);
  file.clear(file.badbit);

  file.open(InFile.c_str());
  if (file.fail()) {
    cerr << "Cannot open file for reading: " << endl;
    return 1;
  }

  vector<string> OutputInput(2);
  const string delimiter = SEPARATOR ;

  //TODO add error checking in getline and string operations
  while (!file.eof()) {
    string line;
    getline(file,line);

    if (line.length() > 0) {
      size_t pos = 0;
      pos = line.find(delimiter);
      OutputInput[0] = line.substr(0, pos);
      line.erase(0, pos + delimiter.length());
      OutputInput[1] = line ;
      mPortsToConnect.push_back(OutputInput);

      //cout << OutputInput[0] << endl;
      //cout << OutputInput[1] << endl;
    }
  }

  file.close();
  //cout << "vec size = " << mPortsToConnect.size() << endl;

  return 0;

}

//-------------------------------------------------------------------------------
/*! \brief Connect ports specified in input XML file InFile
 *
 */
//-------------------------------------------------------------------------------
void JcMess::connectPorts(string InFile)
{
  vector<string> OutputInput(2);

  if ( !(this->parseTextFile(InFile)) ) {
    for (vector<vector<string> >::iterator it = mPortsToConnect.begin();
	 it != mPortsToConnect.end(); ++it) {
      OutputInput = *it;

      //cout << "CON: " <<  OutputInput[0] << " <TO> " <<  OutputInput[1] << endl;

      if (jack_connect(mClient, OutputInput[0].c_str(), OutputInput[1].c_str())) {
	//Display a warining only if the error is not because the ports are already
	//connected, in case the program doesn't display anyting.
	if (EEXIST !=
	    jack_connect(mClient, OutputInput[0].c_str(), OutputInput[1].c_str())) {
	  cerr << "WARNING: port: " << OutputInput[0]
	       << "and port: " << OutputInput[1]
	       << " could not be connected.\n";
	}
      }
    }
  }

}
<|endoftext|>


<commit_before>/**
* Distgen
* Multi-threaded memory access pattern generator
*
* Every thread traverses its own nested series of arrays
* with array sizes as specified. Array sizes correlate
* to distances in a reuse distance histogram, and fit into
* given layers (caches) of the memory hierarchy.
* The idea is to approximate the access pattern of real codes.
*
* Compile with:
*      gcc -o distgen distgen.c distgen_internal.c -fopenmp -O3
*
* Copyright 2016 by LRR-TUM
* Jens Breitbart     <j.breitbart@tum.de>
* Josef Weidendorfer <weidendo@in.tum.de>
*
* Licensed under GNU Lesser General Public License 2.1 or later.
* Some rights reserved. See LICENSE
*/

#include "distgen_internal.h"
#include "distgend.h"

#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

#include <omp.h>

static u64 clockFreq = 0; // assumed frequency for printing cycles
static u64 iters_perstat = 0;

static char *clockFreqDef = "2.4G";

static u64 toU64(char *s, int isSize) {
	u64 num = 0, denom = 1;
	u64 f = isSize ? 1024 : 1000;

	while ((*s >= '0') && (*s <= '9')) {
		num = 10 * num + (*s - '0');
		s++;
	}
	if (*s == '.') {
		s++;
		while ((*s >= '0') && (*s <= '9')) {
			num = 10 * num + (*s - '0');
			denom = 10 * denom;
			s++;
		}
	}

	if ((*s == 'k') || (*s == 'K'))
		num = num * f;
	else if ((*s == 'm') || (*s == 'M'))
		num = num * f * f;
	else if ((*s == 'g') || (*s == 'G'))
		num = num * f * f * f;
	num = num / denom;

	return num;
}

static void printStats(size_t ii, double tDiff, u64 rDiff, u64 wDiff) {
	u64 aDiff = rDiff + wDiff;
	double avg = tDiff * tcount / aDiff * 1000000000.0;
	double cTime = 1000.0 / clockFreq;

	fprintf(stderr, " at%5zu: ", ii);
	fprintf(stderr, " %5.3fs for %4.1f GB => %5.3f GB/s"
					" (per core: %6.3f GB/s)\n",
			tDiff, aDiff * 64.0 / 1000000000.0, aDiff * 64.0 / tDiff / 1000000000.0,
			aDiff * 64.0 / (tDiff * tcount) / 1000000000.0);
	if (verbose > 1)
		fprintf(stderr, "  per access (%llu accesses): %.3f ns (%.1f cycles @ %.1f GHz)\n", aDiff, avg, avg / cTime,
				1.0 / 1000.0 * clockFreq);
}

static size_t get_tcount() {
	static size_t tc = 0;

	if (tc > 0) return tc;

#ifdef _OPENMP
#pragma omp parallel
#pragma omp master
	tc = (size_t)omp_get_num_threads();
#else
	tc = 1;
#endif

	return tc;
}

__attribute__((noreturn)) static void usage(char *argv0) {
	fprintf(stderr, "Benchmark with threads accessing their own nested arrays at cache-line granularity\n\n"
					"Usage: %s [Options] [-<iter>] [<dist1> [<dist2> ... ]]\n"
					"\nParameters:\n"
					"  <iter>       number of times (iterations) accessing arrays (def: 1000)\n"
					"  <dist1>, ... different reuse distances (def: 1 dist with 16MB)\n"
					"\nOptions:\n"
					"  -h           show this help\n"
					"  -p           use pseudo-random access pattern\n"
					"  -d           traversal by dependency chain\n"
					"  -w           write after read on each access\n"
					"  -c <freq>    clock frequency in Hz to show cycles per access (def: %s)\n"
					"  -t <count>   set number of threads to use (def: %zu)\n"
					"  -s <iter>    print perf.stats every few iterations (def: 0 = none)\n"
					"  -v           be verbose\n",
			argv0, clockFreqDef, get_tcount());
	fprintf(stderr, "\nNumbers can end in k/m/g for Kilo/Mega/Giga factor\n");
	exit(1);
}

// this sets global options
void parseOptions(int argc, char *argv[]) {
	int arg;
	u64 dist;

	for (arg = 1; arg < argc; arg++) {
		if (argv[arg][0] == '-') {
			if (argv[arg][1] == 'h') usage(argv[0]);
			if (argv[arg][1] == 'v') {
				verbose++;
				continue;
			}
			if (argv[arg][1] == 'p') {
				pseudoRandom = 1;
				continue;
			}
			if (argv[arg][1] == 'd') {
				depChain = 1;
				continue;
			}
			if (argv[arg][1] == 'w') {
				doWrite = 1;
				continue;
			}
			if (argv[arg][1] == 'c') {
				if (arg + 1 < argc) {
					clockFreq = toU64(argv[arg + 1], 0);
					arg++;
				}
				continue;
			}
			if (argv[arg][1] == 't') {
				if (arg + 1 < argc) {
					tcount = atoi(argv[arg + 1]);
					arg++;
				}
				continue;
			}
			if (argv[arg][1] == 's') {
				if (arg + 1 < argc) {
					iters_perstat = toU64(argv[arg + 1], 0);
					arg++;
				}
				continue;
			}
			iter = (int)toU64(argv[arg] + 1, 0);
			if (iter == 0) {
				fprintf(stderr, "ERROR: expected iteration count, got '%s'\n", argv[arg] + 1);
				usage(argv[0]);
			}
			continue;
		}
		dist = toU64(argv[arg], 1);
		if (dist == 0) {
			fprintf(stderr, "ERROR: expected distance, got '%s'\n", argv[arg]);
			usage(argv[0]);
		}
		addDist(dist);
	}

	// set to defaults if values were not provided

	if (distsUsed == 0) addDist(16 * 1024 * 1024);
	if (iter == 0) iter = 1000;
	if (clockFreq == 0) clockFreq = toU64(clockFreqDef, 0);

	if (tcount == 0) {
		// thread count is the default as given by OpenMP runtime
		tcount = get_tcount();
	} else {
// overwrite thread count of OpenMP runtime
#ifdef _OPENMP
		omp_set_num_threads(tcount);
#else
		// compiled without OpenMP, cannot use more than 1 thread
		if (tcount > 1) {
			fprintf(stderr, "WARNING: OpenMP not available, running sequentially.\n");
			tcount = 1;
		}
#endif
	}

	if (iters_perstat == 0) {
		// no intermediate output
		iters_perstat = iter;
	}
}

int main(int argc, char *argv[]) {
	u64 aCount = 0, aCount1;
	double sum = 0.0;
	double tt, t1, t2;
	double avg, cTime, gData, gFlops, flopsPA;

	parseOptions(argc, argv);

	if (verbose) fprintf(stderr, "Multi-threaded Distance Generator (C) 2015 LRR-TUM\n");

	//--------------------------
	// Initialization
	//--------------------------
	initBufs();

	//--------------------------
	// Run benchmark
	//--------------------------

	fprintf(stderr, "Running %zu iterations, %zu thread(s) ...\n", iter, tcount);
	if (verbose) fprintf(stderr, "  printing statistics every %llu iterations\n", iters_perstat);

	aCount = 0;
	tt = wtime();
	t1 = tt;
	size_t ii = 0;

	// loop over chunks of iterations after which statistics are printed
	while (1) {
		aCount1 = aCount;

#pragma omp parallel reduction(+ : sum) reduction(+ : aCount)
		{
			double tsum = 0.0;
			u64 taCount = 0;

			runBench(buffer[omp_get_thread_num()], iters_perstat, depChain, doWrite, &tsum, &taCount);

			sum += tsum;
			aCount += taCount;
		}

		t2 = wtime();
		ii += iters_perstat;
		if (ii >= iter) break;

		printStats(ii, t2 - t1, aCount - aCount1, doWrite ? (aCount - aCount1) : 0);

		t1 = t2;
	}
	tt = t2 - tt;

	//--------------------------
	// Summary
	//--------------------------

	flopsPA = 1.0;
	if (doWrite) {
		aCount = 2 * aCount;
		flopsPA = .5;
	}

	avg = tt * tcount / aCount * 1000000000.0;
	cTime = 1000000000.0 / clockFreq;
	gData = aCount * 64.0 / 1024.0 / 1024.0 / 1024.0;
	gFlops = aCount * flopsPA / 1000000000.0;

	fprintf(stderr, "Summary: throughput %7.3f GB in %.3f s (per core: %.3f GB)\n", gData, tt, gData / tcount);
	fprintf(stderr, "         bandwidth  %7.3f GB/s (per core: %.3f GB/s)\n", gData / tt, gData / tt / tcount);
	fprintf(stderr, "         GFlop/s    %7.3f GF/s (per core: %.3f GF/s)\n", gFlops / tt, gFlops / tt / tcount);
	fprintf(stderr, "         per acc.   %7.3f ns   (%.1f cycles @ %.2f GHz)\n", avg, avg / cTime,
			1.0 / 1000000000.0 * clockFreq);

	if (verbose) fprintf(stderr, "         accesses   %llu, sum: %g\n", aCount, sum);

	return 0;
}
<commit_msg>Just some more C++.<commit_after>/**
* Distgen
* Multi-threaded memory access pattern generator
*
* Every thread traverses its own nested series of arrays
* with array sizes as specified. Array sizes correlate
* to distances in a reuse distance histogram, and fit into
* given layers (caches) of the memory hierarchy.
* The idea is to approximate the access pattern of real codes.
*
* Compile with:
*      gcc -o distgen distgen.c distgen_internal.c -fopenmp -O3
*
* Copyright 2016 by LRR-TUM
* Jens Breitbart     <j.breitbart@tum.de>
* Josef Weidendorfer <weidendo@in.tum.de>
*
* Licensed under GNU Lesser General Public License 2.1 or later.
* Some rights reserved. See LICENSE
*/

#include "distgen_internal.h"
#include "distgend.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>

#include <omp.h>

#include <malloc.h>

static u64 clockFreq = 0; // assumed frequency for printing cycles
static u64 iters_perstat = 0;

static const char *clockFreqDef = "2.4G";

static u64 toU64(const char *s, int isSize) {
	u64 num = 0, denom = 1;
	u64 f = isSize ? 1024 : 1000;

	while ((*s >= '0') && (*s <= '9')) {
		num = 10 * num + (*s - '0');
		s++;
	}
	if (*s == '.') {
		s++;
		while ((*s >= '0') && (*s <= '9')) {
			num = 10 * num + (*s - '0');
			denom = 10 * denom;
			s++;
		}
	}

	if ((*s == 'k') || (*s == 'K'))
		num = num * f;
	else if ((*s == 'm') || (*s == 'M'))
		num = num * f * f;
	else if ((*s == 'g') || (*s == 'G'))
		num = num * f * f * f;
	num = num / denom;

	return num;
}

static void printStats(size_t ii, double tDiff, u64 rDiff, u64 wDiff) {
	u64 aDiff = rDiff + wDiff;
	double avg = tDiff * tcount / aDiff * 1000000000.0;
	double cTime = 1000.0 / clockFreq;

	fprintf(stderr, " at%5zu: ", ii);
	fprintf(stderr, " %5.3fs for %4.1f GB => %5.3f GB/s"
					" (per core: %6.3f GB/s)\n",
			tDiff, aDiff * 64.0 / 1000000000.0, aDiff * 64.0 / tDiff / 1000000000.0,
			aDiff * 64.0 / (tDiff * tcount) / 1000000000.0);
	if (verbose > 1)
		fprintf(stderr, "  per access (%llu accesses): %.3f ns (%.1f cycles @ %.1f GHz)\n", aDiff, avg, avg / cTime,
				1.0 / 1000.0 * clockFreq);
}

static size_t get_tcount() {
	static size_t tc = 0;

	if (tc > 0) return tc;

#ifdef _OPENMP
#pragma omp parallel
#pragma omp master
	tc = (size_t)omp_get_num_threads();
#else
	tc = 1;
#endif

	return tc;
}

__attribute__((noreturn)) static void usage(char *argv0) {
	fprintf(stderr, "Benchmark with threads accessing their own nested arrays at cache-line granularity\n\n"
					"Usage: %s [Options] [-<iter>] [<dist1> [<dist2> ... ]]\n"
					"\nParameters:\n"
					"  <iter>       number of times (iterations) accessing arrays (def: 1000)\n"
					"  <dist1>, ... different reuse distances (def: 1 dist with 16MB)\n"
					"\nOptions:\n"
					"  -h           show this help\n"
					"  -p           use pseudo-random access pattern\n"
					"  -d           traversal by dependency chain\n"
					"  -w           write after read on each access\n"
					"  -c <freq>    clock frequency in Hz to show cycles per access (def: %s)\n"
					"  -t <count>   set number of threads to use (def: %zu)\n"
					"  -s <iter>    print perf.stats every few iterations (def: 0 = none)\n"
					"  -v           be verbose\n",
			argv0, clockFreqDef, get_tcount());
	fprintf(stderr, "\nNumbers can end in k/m/g for Kilo/Mega/Giga factor\n");
	exit(1);
}

// this sets global options
void parseOptions(int argc, char *argv[]) {
	int arg;
	u64 dist;

	for (arg = 1; arg < argc; arg++) {
		if (argv[arg][0] == '-') {
			if (argv[arg][1] == 'h') usage(argv[0]);
			if (argv[arg][1] == 'v') {
				verbose++;
				continue;
			}
			if (argv[arg][1] == 'p') {
				pseudoRandom = 1;
				continue;
			}
			if (argv[arg][1] == 'd') {
				depChain = 1;
				continue;
			}
			if (argv[arg][1] == 'w') {
				doWrite = 1;
				continue;
			}
			if (argv[arg][1] == 'c') {
				if (arg + 1 < argc) {
					clockFreq = toU64(argv[arg + 1], 0);
					arg++;
				}
				continue;
			}
			if (argv[arg][1] == 't') {
				if (arg + 1 < argc) {
					tcount = atoi(argv[arg + 1]);
					arg++;
				}
				continue;
			}
			if (argv[arg][1] == 's') {
				if (arg + 1 < argc) {
					iters_perstat = toU64(argv[arg + 1], 0);
					arg++;
				}
				continue;
			}
			iter = (int)toU64(argv[arg] + 1, 0);
			if (iter == 0) {
				fprintf(stderr, "ERROR: expected iteration count, got '%s'\n", argv[arg] + 1);
				usage(argv[0]);
			}
			continue;
		}
		dist = toU64(argv[arg], 1);
		if (dist == 0) {
			fprintf(stderr, "ERROR: expected distance, got '%s'\n", argv[arg]);
			usage(argv[0]);
		}
		addDist(dist);
	}

	// set to defaults if values were not provided

	if (distsUsed == 0) addDist(16 * 1024 * 1024);
	if (iter == 0) iter = 1000;
	if (clockFreq == 0) clockFreq = toU64(clockFreqDef, 0);

	if (tcount == 0) {
		// thread count is the default as given by OpenMP runtime
		tcount = get_tcount();
	} else {
// overwrite thread count of OpenMP runtime
#ifdef _OPENMP
		omp_set_num_threads(tcount);
#else
		// compiled without OpenMP, cannot use more than 1 thread
		if (tcount > 1) {
			fprintf(stderr, "WARNING: OpenMP not available, running sequentially.\n");
			tcount = 1;
		}
#endif
	}

	if (iters_perstat == 0) {
		// no intermediate output
		iters_perstat = iter;
	}
}

int main(int argc, char *argv[]) {
	u64 aCount = 0, aCount1;
	double sum = 0.0;
	double tt, t1, t2;
	double avg, cTime, gData, gFlops, flopsPA;

	parseOptions(argc, argv);

	if (verbose) fprintf(stderr, "Multi-threaded Distance Generator (C) 2015 LRR-TUM\n");

	//--------------------------
	// Initialization
	//--------------------------
	initBufs();

	//--------------------------
	// Run benchmark
	//--------------------------

	fprintf(stderr, "Running %zu iterations, %zu thread(s) ...\n", iter, tcount);
	if (verbose) fprintf(stderr, "  printing statistics every %llu iterations\n", iters_perstat);

	aCount = 0;
	tt = wtime();
	t1 = tt;
	size_t ii = 0;

	// loop over chunks of iterations after which statistics are printed
	while (1) {
		aCount1 = aCount;

#pragma omp parallel reduction(+ : sum) reduction(+ : aCount)
		{
			double tsum = 0.0;
			u64 taCount = 0;

			runBench(buffer[omp_get_thread_num()], iters_perstat, depChain, doWrite, &tsum, &taCount);

			sum += tsum;
			aCount += taCount;
		}

		t2 = wtime();
		ii += iters_perstat;
		if (ii >= iter) break;

		printStats(ii, t2 - t1, aCount - aCount1, doWrite ? (aCount - aCount1) : 0);

		t1 = t2;
	}
	tt = t2 - tt;

	//--------------------------
	// Summary
	//--------------------------

	flopsPA = 1.0;
	if (doWrite) {
		aCount = 2 * aCount;
		flopsPA = .5;
	}

	avg = tt * tcount / aCount * 1000000000.0;
	cTime = 1000000000.0 / clockFreq;
	gData = aCount * 64.0 / 1024.0 / 1024.0 / 1024.0;
	gFlops = aCount * flopsPA / 1000000000.0;

	fprintf(stderr, "Summary: throughput %7.3f GB in %.3f s (per core: %.3f GB)\n", gData, tt, gData / tcount);
	fprintf(stderr, "         bandwidth  %7.3f GB/s (per core: %.3f GB/s)\n", gData / tt, gData / tt / tcount);
	fprintf(stderr, "         GFlop/s    %7.3f GF/s (per core: %.3f GF/s)\n", gFlops / tt, gFlops / tt / tcount);
	fprintf(stderr, "         per acc.   %7.3f ns   (%.1f cycles @ %.2f GHz)\n", avg, avg / cTime,
			1.0 / 1000000000.0 * clockFreq);

	if (verbose) fprintf(stderr, "         accesses   %llu, sum: %g\n", aCount, sum);

	return 0;
}
<|endoftext|>