<commit_before>#include "mmcore/CoreInstance.h"
#include "mmcore/MegaMolGraph.h"

#include "mmcore/utility/log/Log.h"
#include "mmcore/utility/log/DefaultTarget.h"

#include "FrameStatistics_Service.hpp"
#include "FrontendServiceCollection.hpp"
#include "GUI_Service.hpp"
#include "Lua_Service_Wrapper.hpp"
#include "OpenGL_GLFW_Service.hpp"
#include "Screenshot_Service.hpp"

#include "mmcore/view/AbstractView_EventConsumption.h"

#include <cxxopts.hpp>
#include "mmcore/LuaAPI.h"
#include "mmcore/utility/graphics/ScreenShotComments.h"

// Filesystem
#if defined(_HAS_CXX17) || ((defined(_MSC_VER) && (_MSC_VER > 1916))) // C++2017 or since VS2019
#include <filesystem>
namespace stdfs = std::filesystem;
#else
// WINDOWS
#ifdef _WIN32
#include <filesystem>
namespace stdfs = std::experimental::filesystem;
#else
// LINUX
#include <experimental/filesystem>
namespace stdfs = std::experimental::filesystem;
#endif
#endif

// make sure that all configuration parameters have sane and useful and EXPLICIT initialization values!
struct CLIConfig {
    std::string program_invocation_string = "";
    std::vector<std::string> project_files = {};
    std::string lua_host_address = "tcp://127.0.0.1:33333";
    bool load_example_project = false;
    bool opengl_khr_debug = true;
};

CLIConfig handle_cli_inputs(int argc, char* argv[]);

bool set_up_example_graph(megamol::core::MegaMolGraph& graph);

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

    auto config = handle_cli_inputs(argc, argv);

    // setup log
    megamol::core::utility::log::Log::DefaultLog.SetLevel(megamol::core::utility::log::Log::LEVEL_ALL);
    megamol::core::utility::log::Log::DefaultLog.SetEchoLevel(megamol::core::utility::log::Log::LEVEL_ALL);
    megamol::core::utility::log::Log::DefaultLog.SetOfflineMessageBufferSize(100);
    megamol::core::utility::log::Log::DefaultLog.SetMainTarget(
        std::make_shared<megamol::core::utility::log::DefaultTarget>(megamol::core::utility::log::Log::LEVEL_ALL));

    megamol::core::CoreInstance core;
    core.Initialise(false); // false makes core not start his own lua service (else we collide on default port)

    const megamol::core::factories::ModuleDescriptionManager& moduleProvider = core.GetModuleDescriptionManager();
    const megamol::core::factories::CallDescriptionManager& callProvider = core.GetCallDescriptionManager();

    megamol::frontend::OpenGL_GLFW_Service gl_service;
    megamol::frontend::OpenGL_GLFW_Service::Config openglConfig;
    openglConfig.windowTitlePrefix = openglConfig.windowTitlePrefix + " ~ Main3000";
    openglConfig.versionMajor = 4;
    openglConfig.versionMinor = 5;
    openglConfig.enableKHRDebug = config.opengl_khr_debug;
    gl_service.setPriority(2);

    megamol::frontend::GUI_Service gui_service;
    megamol::frontend::GUI_Service::Config guiConfig;
    guiConfig.imgui_api = megamol::frontend::GUI_Service::ImGuiAPI::OPEN_GL;
    guiConfig.core_instance = &core;
    // priority must be higher than priority of gl_service (=1)
    // service callbacks get called in order of priority of the service.
    // postGraphRender() and close() are called in reverse order of priorities.
    gui_service.setPriority(23);

    megamol::frontend::Screenshot_Service screenshot_service;
    megamol::frontend::Screenshot_Service::Config screenshotConfig;
    screenshot_service.setPriority(30);

    megamol::frontend::FrameStatistics_Service framestatistics_service;
    megamol::frontend::FrameStatistics_Service::Config framestatisticsConfig;
    // needs to execute before gl_service at frame start, after gl service at frame end
    framestatistics_service.setPriority(1);

    megamol::core::MegaMolGraph graph(core, moduleProvider, callProvider);

    bool lua_imperative_only = false; // allow mmFlush, mmList* and mmGetParam*
    megamol::core::LuaAPI lua_api(graph, lua_imperative_only);
    megamol::frontend::Lua_Service_Wrapper lua_service_wrapper;
    megamol::frontend::Lua_Service_Wrapper::Config luaConfig;
    luaConfig.lua_api_ptr = &lua_api;
    luaConfig.host_address = config.lua_host_address;
    lua_service_wrapper.setPriority(0);

    // clang-format off
    // the main loop is organized around services that can 'do something' in different parts of the main loop.
    // a service is something that implements the AbstractFrontendService interface from 'megamol\frontend_services\include'.
    // a central mechanism that allows services to communicate with each other and with graph modules are _resources_.
    // (see FrontendResource in 'megamol\frontend_resources\include').
    // services may provide resources to the system and they may request resources they need themselves for functioning.
    // think of a resource as a struct (or some type of your choice) that gets wrapped
    // by a helper structure and gets a name attached to it. the fronend makes sure (at least
    // attempts to) to hand each service the resources it requested, or else fail execution of megamol with an error message.
    // resource assignment is done by the name of the resource, so this is a very loose interface based on trust.
    // type safety of resources is ensured in the sense that extracting the wrong type from a FrontendResource will
    // lead to an unhandled bad type cast exception, leading to the shutdown of megamol.
    // clang-format on
    bool run_megamol = true;
    megamol::frontend::FrontendServiceCollection services;
    services.add(gl_service, &openglConfig);
    services.add(gui_service, &guiConfig);
    services.add(lua_service_wrapper, &luaConfig);
    services.add(screenshot_service, &screenshotConfig);
    services.add(framestatistics_service, &framestatisticsConfig);

    // clang-format off
    // TODO: port cinematic as frontend service
    // TODO: FBO-centered rendering (View redesign)
    // => explicit FBOs!
    // => explicit camera / animation time / FBO resources/modules in graph?
    // => do or dont show GUI in screenshots, depending on ...
    // TODO: ZMQ context as frontend resource
    // TODO: port CLI commands from mmconsole
    // TODO: eliminate the core instance:
    //  => extract module/call description manager into new factories; remove from core
    //  => key/value store for CLI configuration as frontend resource (emulate config params)
    // TODO: main3000 raw hot loop performance vs. mmconsole performance
    // TODO: centralize project loading/saving to/from .lua/.png.
    // => has to collect graph serialization from graph, gui state from gui.
    // clang-format on

    const bool init_ok = services.init(); // runs init(config_ptr) on all services with provided config sructs

    if (!init_ok) {
        std::cout << "ERROR: some frontend service could not be initialized successfully. abort. " << std::endl;
        services.close();
        return 1;
    }

    // graph is also a resource that may be accessed by services
    services.getProvidedResources().push_back({"MegaMolGraph", graph});

    // proof of concept: a resource that returns a list of names of available resources
    // used by Lua Wrapper and LuaAPI to return list of available resources via remoteconsole
    const std::function<std::vector<std::string>()> resource_lister = [&]() -> std::vector<std::string> {
        std::vector<std::string> resources;
        for (auto& resource : services.getProvidedResources()) {
            resources.push_back(resource.getIdentifier());
        }
        resources.push_back("FrontendResourcesList");
        return resources;
    };
    services.getProvidedResources().push_back({"FrontendResourcesList", resource_lister});

    // distribute registered resources among registered services.
    const bool resources_ok = services.assignRequestedResources();
    // for each service we call their resource callbacks here:
    //    std::vector<FrontendResource>& getProvidedResources()
    //    std::vector<std::string> getRequestedResourceNames()
    //    void setRequestedResources(std::vector<FrontendResource>& resources)
    if (!resources_ok) {
        std::cout << "ERROR: frontend could not assign requested service resources. abort. " << std::endl;
        run_megamol = false;
    }

    auto frontend_resources = services.getProvidedResources();
    graph.AddModuleDependencies(frontend_resources);

    uint32_t frameID = 0;
    const auto render_next_frame = [&]() -> bool {
        // set global Frame Counter
        core.SetFrameID(frameID++);

        // services: receive inputs (GLFW poll events [keyboard, mouse, window], network, lua)
        services.updateProvidedResources();

        // aka simulation step
        // services: digest new inputs via ModuleResources (GUI digest user inputs, lua digest inputs, network ?)
        // e.g. graph updates, module and call creation via lua and GUI happen here
        services.digestChangedRequestedResources();

        // services tell us wheter we should shut down megamol
        if (services.shouldShutdown())
            return false;

        // actual rendering
        {
            services.preGraphRender(); // e.g. start frame timer, clear render buffers

            graph.RenderNextFrame(); // executes graph views, those digest input events like keyboard/mouse, then render

            services.postGraphRender(); // render GUI, glfw swap buffers, stop frame timer
        }

        services.resetProvidedResources(); // clear buffers holding glfw keyboard+mouse input

        return true;
    };

    // lua can issue rendering of frames
    lua_api.setFlushCallback(render_next_frame);

    // load project files via lua
    for (auto& file : config.project_files) {
        std::string result;
        if (megamol::core::utility::graphics::ScreenShotComments::EndsWithCaseInsensitive(file, ".png")) {
            if (!lua_api.RunString(
                    megamol::core::utility::graphics::ScreenShotComments::GetProjectFromPNG(file), result)) {
                std::cout << "Project file \"" << file << "\" did not execute correctly: " << result << std::endl;
                run_megamol = false;
            }
        } else {
            if (!lua_api.RunFile(file, result)) {
                std::cout << "Project file \"" << file << "\" did not execute correctly: " << result << std::endl;
                run_megamol = false;
            }
        }
    }
    if (config.load_example_project) {
        const bool graph_ok = set_up_example_graph(graph);
        if (!graph_ok) {
            std::cout << "ERROR: frontend could not build graph. abort. " << std::endl;
            run_megamol = false;
        }
    }

    while (run_megamol) {
        run_megamol = render_next_frame();
    }

    // close glfw context, network connections, other system resources
    services.close();

    // clean up modules, calls in graph
    // TODO: implement graph destructor

    return 0;
}

CLIConfig handle_cli_inputs(int argc, char* argv[]) {
    CLIConfig config;

    cxxopts::Options options(argv[0], "MegaMol Frontend 3000");

    config.program_invocation_string = std::string{argv[0]};

    // clang-format off
    // parse input project files
    options.positional_help("<additional project files>");
    options.add_options()
        ("project-files", "projects to load", cxxopts::value<std::vector<std::string>>())
        ("host", "address of lua host server, default: "+config.lua_host_address, cxxopts::value<std::string>())
        ("example", "load minimal test spheres example project", cxxopts::value<bool>())
        ("khrdebug", "enable OpenGL KHR debug messages", cxxopts::value<bool>()->default_value("false"))
        ("help", "print help")
        ;
    // clang-format on

    options.parse_positional({"project-files"});

    try {
        auto parsed_options = options.parse(argc, argv);
        std::string res;

        if (parsed_options.count("help")) {
            std::cout << options.help({""}) << std::endl;
            exit(0);
        }

        // verify project files exist in file system
        if (parsed_options.count("project-files")) {
            const auto& v = parsed_options["project-files"].as<std::vector<std::string>>();
            for (const auto& p : v) {
                if (!stdfs::exists(p)) {
                    std::cout << "Project file \"" << p << "\" does not exist!" << std::endl;
                    std::exit(1);
                }
            }

            config.project_files = v;
        }

        if (parsed_options.count("host")) {
            config.lua_host_address = parsed_options["host"].as<std::string>();
        }

        if (parsed_options.count("example")) {
            config.load_example_project = parsed_options["example"].as<bool>();
        }

        config.opengl_khr_debug = parsed_options["khrdebug"].as<bool>();
    } catch (cxxopts::option_not_exists_exception ex) {
        std::cout << ex.what() << std::endl;
        std::cout << options.help({""}) << std::endl;
        std::exit(1);
    }

    return config;
}

bool set_up_example_graph(megamol::core::MegaMolGraph& graph) {
#define check(X) \
    if (!X)      \
        return false;

    check(graph.CreateModule("View3D_2", "::view"));
    check(graph.CreateModule("SphereRenderer", "::spheres"));
    check(graph.CreateModule("TestSpheresDataSource", "::datasource"));
    check(graph.CreateCall("CallRender3D_2", "::view::rendering", "::spheres::rendering"));
    check(graph.CreateCall("MultiParticleDataCall", "::spheres::getdata", "::datasource::getData"));

    check(graph.SetGraphEntryPoint("::view", megamol::core::view::get_gl_view_runtime_resources_requests(),
        megamol::core::view::view_rendering_execution, megamol::core::view::view_init_rendering_state));

    std::string parameter_name("::datasource::numSpheres");
    auto parameterPtr = graph.FindParameter(parameter_name);
    if (parameterPtr) {
        parameterPtr->ParseValue("23");
    } else {
        std::cout << "ERROR: could not find parameter: " << parameter_name << std::endl;
        return false;
    }

    return true;
}
<commit_msg>frontend: initial window size at startup<commit_after>#include "mmcore/CoreInstance.h"
#include "mmcore/MegaMolGraph.h"

#include "mmcore/utility/log/Log.h"
#include "mmcore/utility/log/DefaultTarget.h"

#include "FrameStatistics_Service.hpp"
#include "FrontendServiceCollection.hpp"
#include "GUI_Service.hpp"
#include "Lua_Service_Wrapper.hpp"
#include "OpenGL_GLFW_Service.hpp"
#include "Screenshot_Service.hpp"

#include "mmcore/view/AbstractView_EventConsumption.h"

#include <cxxopts.hpp>
#include "mmcore/LuaAPI.h"
#include "mmcore/utility/graphics/ScreenShotComments.h"

// Filesystem
#if defined(_HAS_CXX17) || ((defined(_MSC_VER) && (_MSC_VER > 1916))) // C++2017 or since VS2019
#include <filesystem>
namespace stdfs = std::filesystem;
#else
// WINDOWS
#ifdef _WIN32
#include <filesystem>
namespace stdfs = std::experimental::filesystem;
#else
// LINUX
#include <experimental/filesystem>
namespace stdfs = std::experimental::filesystem;
#endif
#endif

// make sure that all configuration parameters have sane and useful and EXPLICIT initialization values!
struct CLIConfig {
    std::string program_invocation_string = "";
    std::vector<std::string> project_files = {};
    std::string lua_host_address = "tcp://127.0.0.1:33333";
    bool load_example_project = false;
    bool opengl_khr_debug = true;
    std::array<unsigned int, 2> window_size = {0, 0};
};

CLIConfig handle_cli_inputs(int argc, char* argv[]);

bool set_up_example_graph(megamol::core::MegaMolGraph& graph);

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

    auto config = handle_cli_inputs(argc, argv);

    // setup log
    megamol::core::utility::log::Log::DefaultLog.SetLevel(megamol::core::utility::log::Log::LEVEL_ALL);
    megamol::core::utility::log::Log::DefaultLog.SetEchoLevel(megamol::core::utility::log::Log::LEVEL_ALL);
    megamol::core::utility::log::Log::DefaultLog.SetOfflineMessageBufferSize(100);
    megamol::core::utility::log::Log::DefaultLog.SetMainTarget(
        std::make_shared<megamol::core::utility::log::DefaultTarget>(megamol::core::utility::log::Log::LEVEL_ALL));

    megamol::core::CoreInstance core;
    core.Initialise(false); // false makes core not start his own lua service (else we collide on default port)

    const megamol::core::factories::ModuleDescriptionManager& moduleProvider = core.GetModuleDescriptionManager();
    const megamol::core::factories::CallDescriptionManager& callProvider = core.GetCallDescriptionManager();

    megamol::frontend::OpenGL_GLFW_Service gl_service;
    megamol::frontend::OpenGL_GLFW_Service::Config openglConfig;
    openglConfig.windowTitlePrefix = openglConfig.windowTitlePrefix + " ~ Main3000";
    openglConfig.versionMajor = 4;
    openglConfig.versionMinor = 5;
    openglConfig.enableKHRDebug = config.opengl_khr_debug;
    openglConfig.windowPlacement.w = config.window_size[0];
    openglConfig.windowPlacement.h = config.window_size[1];
    openglConfig.windowPlacement.size = config.window_size[0] > 0 && config.window_size[1] > 0;
    gl_service.setPriority(2);

    megamol::frontend::GUI_Service gui_service;
    megamol::frontend::GUI_Service::Config guiConfig;
    guiConfig.imgui_api = megamol::frontend::GUI_Service::ImGuiAPI::OPEN_GL;
    guiConfig.core_instance = &core;
    // priority must be higher than priority of gl_service (=1)
    // service callbacks get called in order of priority of the service.
    // postGraphRender() and close() are called in reverse order of priorities.
    gui_service.setPriority(23);

    megamol::frontend::Screenshot_Service screenshot_service;
    megamol::frontend::Screenshot_Service::Config screenshotConfig;
    screenshot_service.setPriority(30);

    megamol::frontend::FrameStatistics_Service framestatistics_service;
    megamol::frontend::FrameStatistics_Service::Config framestatisticsConfig;
    // needs to execute before gl_service at frame start, after gl service at frame end
    framestatistics_service.setPriority(1);

    megamol::core::MegaMolGraph graph(core, moduleProvider, callProvider);

    bool lua_imperative_only = false; // allow mmFlush, mmList* and mmGetParam*
    megamol::core::LuaAPI lua_api(graph, lua_imperative_only);
    megamol::frontend::Lua_Service_Wrapper lua_service_wrapper;
    megamol::frontend::Lua_Service_Wrapper::Config luaConfig;
    luaConfig.lua_api_ptr = &lua_api;
    luaConfig.host_address = config.lua_host_address;
    lua_service_wrapper.setPriority(0);

    // clang-format off
    // the main loop is organized around services that can 'do something' in different parts of the main loop.
    // a service is something that implements the AbstractFrontendService interface from 'megamol\frontend_services\include'.
    // a central mechanism that allows services to communicate with each other and with graph modules are _resources_.
    // (see FrontendResource in 'megamol\frontend_resources\include').
    // services may provide resources to the system and they may request resources they need themselves for functioning.
    // think of a resource as a struct (or some type of your choice) that gets wrapped
    // by a helper structure and gets a name attached to it. the fronend makes sure (at least
    // attempts to) to hand each service the resources it requested, or else fail execution of megamol with an error message.
    // resource assignment is done by the name of the resource, so this is a very loose interface based on trust.
    // type safety of resources is ensured in the sense that extracting the wrong type from a FrontendResource will
    // lead to an unhandled bad type cast exception, leading to the shutdown of megamol.
    // clang-format on
    bool run_megamol = true;
    megamol::frontend::FrontendServiceCollection services;
    services.add(gl_service, &openglConfig);
    services.add(gui_service, &guiConfig);
    services.add(lua_service_wrapper, &luaConfig);
    services.add(screenshot_service, &screenshotConfig);
    services.add(framestatistics_service, &framestatisticsConfig);

    // clang-format off
    // TODO: port cinematic as frontend service
    // TODO: FBO-centered rendering (View redesign)
    // => explicit FBOs!
    // => explicit camera / animation time / FBO resources/modules in graph?
    // => do or dont show GUI in screenshots, depending on ...
    // TODO: ZMQ context as frontend resource
    // TODO: port CLI commands from mmconsole
    // TODO: eliminate the core instance:
    //  => extract module/call description manager into new factories; remove from core
    //  => key/value store for CLI configuration as frontend resource (emulate config params)
    // TODO: main3000 raw hot loop performance vs. mmconsole performance
    // TODO: centralize project loading/saving to/from .lua/.png.
    // => has to collect graph serialization from graph, gui state from gui.
    // clang-format on

    const bool init_ok = services.init(); // runs init(config_ptr) on all services with provided config sructs

    if (!init_ok) {
        std::cout << "ERROR: some frontend service could not be initialized successfully. abort. " << std::endl;
        services.close();
        return 1;
    }

    // graph is also a resource that may be accessed by services
    services.getProvidedResources().push_back({"MegaMolGraph", graph});

    // proof of concept: a resource that returns a list of names of available resources
    // used by Lua Wrapper and LuaAPI to return list of available resources via remoteconsole
    const std::function<std::vector<std::string>()> resource_lister = [&]() -> std::vector<std::string> {
        std::vector<std::string> resources;
        for (auto& resource : services.getProvidedResources()) {
            resources.push_back(resource.getIdentifier());
        }
        resources.push_back("FrontendResourcesList");
        return resources;
    };
    services.getProvidedResources().push_back({"FrontendResourcesList", resource_lister});

    // distribute registered resources among registered services.
    const bool resources_ok = services.assignRequestedResources();
    // for each service we call their resource callbacks here:
    //    std::vector<FrontendResource>& getProvidedResources()
    //    std::vector<std::string> getRequestedResourceNames()
    //    void setRequestedResources(std::vector<FrontendResource>& resources)
    if (!resources_ok) {
        std::cout << "ERROR: frontend could not assign requested service resources. abort. " << std::endl;
        run_megamol = false;
    }

    auto frontend_resources = services.getProvidedResources();
    graph.AddModuleDependencies(frontend_resources);

    uint32_t frameID = 0;
    const auto render_next_frame = [&]() -> bool {
        // set global Frame Counter
        core.SetFrameID(frameID++);

        // services: receive inputs (GLFW poll events [keyboard, mouse, window], network, lua)
        services.updateProvidedResources();

        // aka simulation step
        // services: digest new inputs via ModuleResources (GUI digest user inputs, lua digest inputs, network ?)
        // e.g. graph updates, module and call creation via lua and GUI happen here
        services.digestChangedRequestedResources();

        // services tell us wheter we should shut down megamol
        if (services.shouldShutdown())
            return false;

        // actual rendering
        {
            services.preGraphRender(); // e.g. start frame timer, clear render buffers

            graph.RenderNextFrame(); // executes graph views, those digest input events like keyboard/mouse, then render

            services.postGraphRender(); // render GUI, glfw swap buffers, stop frame timer
        }

        services.resetProvidedResources(); // clear buffers holding glfw keyboard+mouse input

        return true;
    };

    // lua can issue rendering of frames
    lua_api.setFlushCallback(render_next_frame);

    // load project files via lua
    for (auto& file : config.project_files) {
        std::string result;
        if (megamol::core::utility::graphics::ScreenShotComments::EndsWithCaseInsensitive(file, ".png")) {
            if (!lua_api.RunString(
                    megamol::core::utility::graphics::ScreenShotComments::GetProjectFromPNG(file), result)) {
                std::cout << "Project file \"" << file << "\" did not execute correctly: " << result << std::endl;
                run_megamol = false;
            }
        } else {
            if (!lua_api.RunFile(file, result)) {
                std::cout << "Project file \"" << file << "\" did not execute correctly: " << result << std::endl;
                run_megamol = false;
            }
        }
    }
    if (config.load_example_project) {
        const bool graph_ok = set_up_example_graph(graph);
        if (!graph_ok) {
            std::cout << "ERROR: frontend could not build graph. abort. " << std::endl;
            run_megamol = false;
        }
    }

    while (run_megamol) {
        run_megamol = render_next_frame();
    }

    // close glfw context, network connections, other system resources
    services.close();

    // clean up modules, calls in graph
    // TODO: implement graph destructor

    return 0;
}

CLIConfig handle_cli_inputs(int argc, char* argv[]) {
    CLIConfig config;

    cxxopts::Options options(argv[0], "MegaMol Frontend 3000");

    config.program_invocation_string = std::string{argv[0]};

    // clang-format off
    // parse input project files
    options.positional_help("<additional project files>");
    options.add_options()
        ("project-files", "projects to load", cxxopts::value<std::vector<std::string>>())
        ("host", "address of lua host server, default: "+config.lua_host_address, cxxopts::value<std::string>())
        ("example", "load minimal test spheres example project", cxxopts::value<bool>())
        ("khrdebug", "enable OpenGL KHR debug messages", cxxopts::value<bool>()->default_value("false"))
        ("help", "print help")
        ;
    // clang-format on

    options.parse_positional({"project-files"});

    try {
        auto parsed_options = options.parse(argc, argv);
        std::string res;

        if (parsed_options.count("help")) {
            std::cout << options.help({""}) << std::endl;
            exit(0);
        }

        // verify project files exist in file system
        if (parsed_options.count("project-files")) {
            const auto& v = parsed_options["project-files"].as<std::vector<std::string>>();
            for (const auto& p : v) {
                if (!stdfs::exists(p)) {
                    std::cout << "Project file \"" << p << "\" does not exist!" << std::endl;
                    std::exit(1);
                }
            }

            config.project_files = v;
        }

        if (parsed_options.count("host")) {
            config.lua_host_address = parsed_options["host"].as<std::string>();
        }

        if (parsed_options.count("example")) {
            config.load_example_project = parsed_options["example"].as<bool>();
        }

        config.opengl_khr_debug = parsed_options["khrdebug"].as<bool>();
    } catch (cxxopts::option_not_exists_exception ex) {
        std::cout << ex.what() << std::endl;
        std::cout << options.help({""}) << std::endl;
        std::exit(1);
    }

    return config;
}

bool set_up_example_graph(megamol::core::MegaMolGraph& graph) {
#define check(X) \
    if (!X)      \
        return false;

    check(graph.CreateModule("View3D_2", "::view"));
    check(graph.CreateModule("SphereRenderer", "::spheres"));
    check(graph.CreateModule("TestSpheresDataSource", "::datasource"));
    check(graph.CreateCall("CallRender3D_2", "::view::rendering", "::spheres::rendering"));
    check(graph.CreateCall("MultiParticleDataCall", "::spheres::getdata", "::datasource::getData"));

    check(graph.SetGraphEntryPoint("::view", megamol::core::view::get_gl_view_runtime_resources_requests(),
        megamol::core::view::view_rendering_execution, megamol::core::view::view_init_rendering_state));

    std::string parameter_name("::datasource::numSpheres");
    auto parameterPtr = graph.FindParameter(parameter_name);
    if (parameterPtr) {
        parameterPtr->ParseValue("23");
    } else {
        std::cout << "ERROR: could not find parameter: " << parameter_name << std::endl;
        return false;
    }

    return true;
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/cpu/backend/x64/x64_code_cache.h"

#include <cstdlib>
#include <cstring>

#include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
#include "xenia/base/platform_win.h"
#include "xenia/cpu/function.h"

// When enabled, this will use Windows 8 APIs to get unwind info.
// TODO(benvanik): figure out why the callback variant doesn't work.
#define USE_GROWABLE_FUNCTION_TABLE

namespace xe {
namespace cpu {
namespace backend {
namespace x64 {

// Size of unwind info per function.
// TODO(benvanik): move this to emitter.
static const uint32_t kUnwindInfoSize = 4 + (2 * 1 + 2 + 2);

class Win32X64CodeCache : public X64CodeCache {
 public:
  Win32X64CodeCache();
  ~Win32X64CodeCache() override;

  bool Initialize() override;

  void* LookupUnwindInfo(uint64_t host_pc) override;

 private:
  UnwindReservation RequestUnwindReservation(uint8_t* entry_address) override;
  void PlaceCode(uint32_t guest_address, void* machine_code, size_t code_size,
                 size_t stack_size, void* code_address,
                 UnwindReservation unwind_reservation) override;

  void InitializeUnwindEntry(uint8_t* unwind_entry_address,
                             size_t unwind_table_slot, void* code_address,
                             size_t code_size, size_t stack_size);

  // Growable function table system handle.
  void* unwind_table_handle_ = nullptr;
  // Actual unwind table entries.
  std::vector<RUNTIME_FUNCTION> unwind_table_;
  // Current number of entries in the table.
  std::atomic<uint32_t> unwind_table_count_ = {0};
};

std::unique_ptr<X64CodeCache> X64CodeCache::Create() {
  return std::make_unique<Win32X64CodeCache>();
}

Win32X64CodeCache::Win32X64CodeCache() = default;

Win32X64CodeCache::~Win32X64CodeCache() {
#ifdef USE_GROWABLE_FUNCTION_TABLE
  if (unwind_table_handle_) {
    RtlDeleteGrowableFunctionTable(unwind_table_handle_);
  }
#else
  if (generated_code_base_) {
    RtlDeleteFunctionTable(reinterpret_cast<PRUNTIME_FUNCTION>(
        reinterpret_cast<DWORD64>(generated_code_base_) | 0x3));
  }
#endif  // USE_GROWABLE_FUNCTION_TABLE
}

bool Win32X64CodeCache::Initialize() {
  if (!X64CodeCache::Initialize()) {
    return false;
  }

  // Compute total number of unwind entries we should allocate.
  // We don't support reallocing right now, so this should be high.
  unwind_table_.resize(kMaximumFunctionCount);

#ifdef USE_GROWABLE_FUNCTION_TABLE
  // Create table and register with the system. It's empty now, but we'll grow
  // it as functions are added.
  if (RtlAddGrowableFunctionTable(
          &unwind_table_handle_, unwind_table_.data(), unwind_table_count_,
          DWORD(unwind_table_.size()),
          reinterpret_cast<ULONG_PTR>(generated_code_base_),
          reinterpret_cast<ULONG_PTR>(generated_code_base_ +
                                      kGeneratedCodeSize))) {
    XELOGE("Unable to create unwind function table");
    return false;
  }
#else
  // Install a callback that the debugger will use to lookup unwind info on
  // demand.
  if (!RtlInstallFunctionTableCallback(
          reinterpret_cast<DWORD64>(generated_code_base_) | 0x3,
          reinterpret_cast<DWORD64>(generated_code_base_), kGeneratedCodeSize,
          [](uintptr_t control_pc, void* context) {
            auto code_cache = reinterpret_cast<X64CodeCache*>(context);
            return reinterpret_cast<PRUNTIME_FUNCTION>(
                code_cache->LookupUnwindEntry(control_pc));
          },
          this, nullptr)) {
    XELOGE("Unable to install function table callback");
    return false;
  }
#endif  // USE_GROWABLE_FUNCTION_TABLE

  return true;
}

Win32X64CodeCache::UnwindReservation
Win32X64CodeCache::RequestUnwindReservation(uint8_t* entry_address) {
  UnwindReservation unwind_reservation;
  unwind_reservation.data_size = xe::round_up(kUnwindInfoSize, 16);
  unwind_reservation.table_slot = ++unwind_table_count_;
  unwind_reservation.entry_address = entry_address;
  assert_false(unwind_table_count_ >= kMaximumFunctionCount);

  return unwind_reservation;
}

void Win32X64CodeCache::PlaceCode(uint32_t guest_address, void* machine_code,
                                  size_t code_size, size_t stack_size,
                                  void* code_address,
                                  UnwindReservation unwind_reservation) {
  // Add unwind info.
  InitializeUnwindEntry(unwind_reservation.entry_address,
                        unwind_reservation.table_slot, code_address, code_size,
                        stack_size);

#ifdef USE_GROWABLE_FUNCTION_TABLE
  // Notify that the unwind table has grown.
  // We do this outside of the lock, but with the latest total count.
  RtlGrowFunctionTable(unwind_table_handle_, unwind_table_count_);
#endif  // USE_GROWABLE_FUNCTION_TABLE

  // This isn't needed on x64 (probably), but is convention.
  FlushInstructionCache(GetCurrentProcess(), code_address, code_size);
}

// http://msdn.microsoft.com/en-us/library/ssa62fwe.aspx
typedef enum _UNWIND_OP_CODES {
  UWOP_PUSH_NONVOL = 0, /* info == register number */
  UWOP_ALLOC_LARGE,     /* no info, alloc size in next 2 slots */
  UWOP_ALLOC_SMALL,     /* info == size of allocation / 8 - 1 */
  UWOP_SET_FPREG,       /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
  UWOP_SAVE_NONVOL,     /* info == register number, offset in next slot */
  UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
  UWOP_SAVE_XMM128,     /* info == XMM reg number, offset in next slot */
  UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
  UWOP_PUSH_MACHFRAME   /* info == 0: no error-code, 1: error-code */
} UNWIND_CODE_OPS;
class UNWIND_REGISTER {
 public:
  enum _ {
    RAX = 0,
    RCX = 1,
    RDX = 2,
    RBX = 3,
    RSP = 4,
    RBP = 5,
    RSI = 6,
    RDI = 7,
    R8 = 8,
    R9 = 9,
    R10 = 10,
    R11 = 11,
    R12 = 12,
    R13 = 13,
    R14 = 14,
    R15 = 15,
  };
};

typedef union _UNWIND_CODE {
  struct {
    uint8_t CodeOffset;
    uint8_t UnwindOp : 4;
    uint8_t OpInfo : 4;
  };
  USHORT FrameOffset;
} UNWIND_CODE, *PUNWIND_CODE;

typedef struct _UNWIND_INFO {
  uint8_t Version : 3;
  uint8_t Flags : 5;
  uint8_t SizeOfProlog;
  uint8_t CountOfCodes;
  uint8_t FrameRegister : 4;
  uint8_t FrameOffset : 4;
  UNWIND_CODE UnwindCode[1];
  /*  UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
   *   union {
   *       OPTIONAL ULONG ExceptionHandler;
   *       OPTIONAL ULONG FunctionEntry;
   *   };
   *   OPTIONAL ULONG ExceptionData[]; */
} UNWIND_INFO, *PUNWIND_INFO;

void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
                                              size_t unwind_table_slot,
                                              void* code_address,
                                              size_t code_size,
                                              size_t stack_size) {
  auto unwind_info = reinterpret_cast<UNWIND_INFO*>(unwind_entry_address);

  if (!stack_size) {
    // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
    unwind_info->Version = 1;
    unwind_info->Flags = 0;
    unwind_info->SizeOfProlog = 0;
    unwind_info->CountOfCodes = 0;
    unwind_info->FrameRegister = 0;
    unwind_info->FrameOffset = 0;
  } else if (stack_size <= 128) {
    uint8_t prolog_size = 4;

    // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
    unwind_info->Version = 1;
    unwind_info->Flags = 0;
    unwind_info->SizeOfProlog = prolog_size;
    unwind_info->CountOfCodes = 1;
    unwind_info->FrameRegister = 0;
    unwind_info->FrameOffset = 0;

    // http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
    size_t co = 0;
    auto& unwind_code = unwind_info->UnwindCode[co++];
    unwind_code.CodeOffset =
        14;  // end of instruction + 1 == offset of next instruction
    unwind_code.UnwindOp = UWOP_ALLOC_SMALL;
    unwind_code.OpInfo = stack_size / 8 - 1;
  } else {
    // TODO(benvanik): take as parameters?
    uint8_t prolog_size = 7;

    // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
    unwind_info->Version = 1;
    unwind_info->Flags = 0;
    unwind_info->SizeOfProlog = prolog_size;
    unwind_info->CountOfCodes = 2;
    unwind_info->FrameRegister = 0;
    unwind_info->FrameOffset = 0;

    // http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
    size_t co = 0;
    auto& unwind_code = unwind_info->UnwindCode[co++];
    unwind_code.CodeOffset =
        7;  // end of instruction + 1 == offset of next instruction
    unwind_code.UnwindOp = UWOP_ALLOC_LARGE;
    unwind_code.OpInfo = 0;

    assert_true((stack_size / 8) < 65536u);
    unwind_code = unwind_info->UnwindCode[co++];
    unwind_code.FrameOffset = (USHORT)(stack_size) / 8;
  }

  // Add entry.
  auto& fn_entry = unwind_table_[unwind_table_slot];
  fn_entry.BeginAddress =
      (DWORD)(reinterpret_cast<uint8_t*>(code_address) - generated_code_base_);
  fn_entry.EndAddress = (DWORD)(fn_entry.BeginAddress + code_size);
  fn_entry.UnwindData = (DWORD)(unwind_entry_address - generated_code_base_);
}

void* Win32X64CodeCache::LookupUnwindInfo(uint64_t host_pc) {
  return std::bsearch(
      &host_pc, unwind_table_.data(), unwind_table_count_ + 1,
      sizeof(RUNTIME_FUNCTION),
      [](const void* key_ptr, const void* element_ptr) {
        auto key =
            *reinterpret_cast<const uintptr_t*>(key_ptr) - kGeneratedCodeBase;
        auto element = reinterpret_cast<const RUNTIME_FUNCTION*>(element_ptr);
        if (key < element->BeginAddress) {
          return -1;
        } else if (key > element->EndAddress) {
          return 1;
        } else {
          return 0;
        }
      });
}

}  // namespace x64
}  // namespace backend
}  // namespace cpu
}  // namespace xe
<commit_msg>[x64] Fix unwind info bug; Cleanup win code cache<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/cpu/backend/x64/x64_code_cache.h"

#include <cstdlib>
#include <cstring>

#include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
#include "xenia/base/platform_win.h"
#include "xenia/cpu/function.h"

// When enabled, this will use Windows 8 APIs to get unwind info.
// TODO(benvanik): figure out why the callback variant doesn't work.
#define USE_GROWABLE_FUNCTION_TABLE

namespace xe {
namespace cpu {
namespace backend {
namespace x64 {

// http://msdn.microsoft.com/en-us/library/ssa62fwe.aspx
typedef enum _UNWIND_OP_CODES {
  UWOP_PUSH_NONVOL = 0, /* info == register number */
  UWOP_ALLOC_LARGE,     /* no info, alloc size in next 2 slots */
  UWOP_ALLOC_SMALL,     /* info == size of allocation / 8 - 1 */
  UWOP_SET_FPREG,       /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
  UWOP_SAVE_NONVOL,     /* info == register number, offset in next slot */
  UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
  UWOP_SAVE_XMM128,     /* info == XMM reg number, offset in next slot */
  UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
  UWOP_PUSH_MACHFRAME   /* info == 0: no error-code, 1: error-code */
} UNWIND_CODE_OPS;
class UNWIND_REGISTER {
 public:
  enum _ {
    RAX = 0,
    RCX = 1,
    RDX = 2,
    RBX = 3,
    RSP = 4,
    RBP = 5,
    RSI = 6,
    RDI = 7,
    R8 = 8,
    R9 = 9,
    R10 = 10,
    R11 = 11,
    R12 = 12,
    R13 = 13,
    R14 = 14,
    R15 = 15,
  };
};

typedef union _UNWIND_CODE {
  struct {
    uint8_t CodeOffset;
    uint8_t UnwindOp : 4;
    uint8_t OpInfo : 4;
  };
  USHORT FrameOffset;
} UNWIND_CODE, *PUNWIND_CODE;

typedef struct _UNWIND_INFO {
  uint8_t Version : 3;
  uint8_t Flags : 5;
  uint8_t SizeOfProlog;
  uint8_t CountOfCodes;
  uint8_t FrameRegister : 4;
  uint8_t FrameOffset : 4;
  UNWIND_CODE UnwindCode[1];
  /*  UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
   *   union {
   *       OPTIONAL ULONG ExceptionHandler;
   *       OPTIONAL ULONG FunctionEntry;
   *   };
   *   OPTIONAL ULONG ExceptionData[]; */
} UNWIND_INFO, *PUNWIND_INFO;

// Size of unwind info per function.
// TODO(benvanik): move this to emitter.
static const uint32_t kUnwindInfoSize =
    sizeof(UNWIND_INFO) + (sizeof(UNWIND_CODE) * (6 - 1));

class Win32X64CodeCache : public X64CodeCache {
 public:
  Win32X64CodeCache();
  ~Win32X64CodeCache() override;

  bool Initialize() override;

  void* LookupUnwindInfo(uint64_t host_pc) override;

 private:
  UnwindReservation RequestUnwindReservation(uint8_t* entry_address) override;
  void PlaceCode(uint32_t guest_address, void* machine_code, size_t code_size,
                 size_t stack_size, void* code_address,
                 UnwindReservation unwind_reservation) override;

  void InitializeUnwindEntry(uint8_t* unwind_entry_address,
                             size_t unwind_table_slot, void* code_address,
                             size_t code_size, size_t stack_size);

  // Growable function table system handle.
  void* unwind_table_handle_ = nullptr;
  // Actual unwind table entries.
  std::vector<RUNTIME_FUNCTION> unwind_table_;
  // Current number of entries in the table.
  std::atomic<uint32_t> unwind_table_count_ = {0};
};

std::unique_ptr<X64CodeCache> X64CodeCache::Create() {
  return std::make_unique<Win32X64CodeCache>();
}

Win32X64CodeCache::Win32X64CodeCache() = default;

Win32X64CodeCache::~Win32X64CodeCache() {
#ifdef USE_GROWABLE_FUNCTION_TABLE
  if (unwind_table_handle_) {
    RtlDeleteGrowableFunctionTable(unwind_table_handle_);
  }
#else
  if (generated_code_base_) {
    RtlDeleteFunctionTable(reinterpret_cast<PRUNTIME_FUNCTION>(
        reinterpret_cast<DWORD64>(generated_code_base_) | 0x3));
  }
#endif  // USE_GROWABLE_FUNCTION_TABLE
}

bool Win32X64CodeCache::Initialize() {
  if (!X64CodeCache::Initialize()) {
    return false;
  }

  // Compute total number of unwind entries we should allocate.
  // We don't support reallocing right now, so this should be high.
  unwind_table_.resize(kMaximumFunctionCount);

#ifdef USE_GROWABLE_FUNCTION_TABLE
  // Create table and register with the system. It's empty now, but we'll grow
  // it as functions are added.
  if (RtlAddGrowableFunctionTable(
          &unwind_table_handle_, unwind_table_.data(), unwind_table_count_,
          DWORD(unwind_table_.size()),
          reinterpret_cast<ULONG_PTR>(generated_code_base_),
          reinterpret_cast<ULONG_PTR>(generated_code_base_ +
                                      kGeneratedCodeSize))) {
    XELOGE("Unable to create unwind function table");
    return false;
  }
#else
  // Install a callback that the debugger will use to lookup unwind info on
  // demand.
  if (!RtlInstallFunctionTableCallback(
          reinterpret_cast<DWORD64>(generated_code_base_) | 0x3,
          reinterpret_cast<DWORD64>(generated_code_base_), kGeneratedCodeSize,
          [](DWORD64 control_pc, PVOID context) {
            auto code_cache = reinterpret_cast<Win32X64CodeCache*>(context);
            return reinterpret_cast<PRUNTIME_FUNCTION>(
                code_cache->LookupUnwindInfo(control_pc));
          },
          this, nullptr)) {
    XELOGE("Unable to install function table callback");
    return false;
  }
#endif  // USE_GROWABLE_FUNCTION_TABLE

  return true;
}

Win32X64CodeCache::UnwindReservation
Win32X64CodeCache::RequestUnwindReservation(uint8_t* entry_address) {
  UnwindReservation unwind_reservation;
  unwind_reservation.data_size = xe::round_up(kUnwindInfoSize, 16);
  unwind_reservation.table_slot = ++unwind_table_count_;
  unwind_reservation.entry_address = entry_address;
  assert_false(unwind_table_count_ >= kMaximumFunctionCount);

  return unwind_reservation;
}

void Win32X64CodeCache::PlaceCode(uint32_t guest_address, void* machine_code,
                                  size_t code_size, size_t stack_size,
                                  void* code_address,
                                  UnwindReservation unwind_reservation) {
  // Add unwind info.
  InitializeUnwindEntry(unwind_reservation.entry_address,
                        unwind_reservation.table_slot, code_address, code_size,
                        stack_size);

#ifdef USE_GROWABLE_FUNCTION_TABLE
  // Notify that the unwind table has grown.
  // We do this outside of the lock, but with the latest total count.
  RtlGrowFunctionTable(unwind_table_handle_, unwind_table_count_);
#endif  // USE_GROWABLE_FUNCTION_TABLE

  // This isn't needed on x64 (probably), but is convention.
  FlushInstructionCache(GetCurrentProcess(), code_address, code_size);
}

void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
                                              size_t unwind_table_slot,
                                              void* code_address,
                                              size_t code_size,
                                              size_t stack_size) {
  auto unwind_info = reinterpret_cast<UNWIND_INFO*>(unwind_entry_address);
  UNWIND_CODE* unwind_code = nullptr;

  if (!stack_size) {
    // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
    unwind_info->Version = 1;
    unwind_info->Flags = 0;
    unwind_info->SizeOfProlog = 0;
    unwind_info->CountOfCodes = 0;
    unwind_info->FrameRegister = 0;
    unwind_info->FrameOffset = 0;
  } else if (stack_size <= 128) {
    uint8_t prolog_size = 4;

    // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
    unwind_info->Version = 1;
    unwind_info->Flags = 0;
    unwind_info->SizeOfProlog = prolog_size;
    unwind_info->CountOfCodes = 0;
    unwind_info->FrameRegister = 0;
    unwind_info->FrameOffset = 0;

    // http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
    unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++];
    unwind_code->CodeOffset =
        14;  // end of instruction + 1 == offset of next instruction
    unwind_code->UnwindOp = UWOP_ALLOC_SMALL;
    unwind_code->OpInfo = stack_size / 8 - 1;
  } else {
    // TODO(benvanik): take as parameters?
    uint8_t prolog_size = 7;

    // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
    unwind_info->Version = 1;
    unwind_info->Flags = 0;
    unwind_info->SizeOfProlog = prolog_size;
    unwind_info->CountOfCodes = 0;
    unwind_info->FrameRegister = 0;
    unwind_info->FrameOffset = 0;

    // http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
    unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++];
    unwind_code->CodeOffset =
        7;  // end of instruction + 1 == offset of next instruction
    unwind_code->UnwindOp = UWOP_ALLOC_LARGE;
    unwind_code->OpInfo = 0;  // One slot for size

    assert_true((stack_size / 8) < 65536u);
    unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++];
    unwind_code->FrameOffset = (USHORT)(stack_size) / 8;
  }

  if (unwind_info->CountOfCodes % 1) {
    // Count of unwind codes must always be even.
    std::memset(&unwind_info->UnwindCode[unwind_info->CountOfCodes + 1], 0,
                sizeof(UNWIND_CODE));
  }

  // Add entry.
  auto& fn_entry = unwind_table_[unwind_table_slot];
  fn_entry.BeginAddress =
      (DWORD)(reinterpret_cast<uint8_t*>(code_address) - generated_code_base_);
  fn_entry.EndAddress = (DWORD)(fn_entry.BeginAddress + code_size);
  fn_entry.UnwindData = (DWORD)(unwind_entry_address - generated_code_base_);
}

void* Win32X64CodeCache::LookupUnwindInfo(uint64_t host_pc) {
  return std::bsearch(
      &host_pc, unwind_table_.data(), unwind_table_count_ + 1,
      sizeof(RUNTIME_FUNCTION),
      [](const void* key_ptr, const void* element_ptr) {
        auto key =
            *reinterpret_cast<const uintptr_t*>(key_ptr) - kGeneratedCodeBase;
        auto element = reinterpret_cast<const RUNTIME_FUNCTION*>(element_ptr);
        if (key < element->BeginAddress) {
          return -1;
        } else if (key > element->EndAddress) {
          return 1;
        } else {
          return 0;
        }
      });
}

}  // namespace x64
}  // namespace backend
}  // namespace cpu
}  // namespace xe
<|endoftext|>


<commit_before>#ifndef REPORTDESIGN_API_REPORTENGINEJFREE_HXX
#define REPORTDESIGN_API_REPORTENGINEJFREE_HXX
/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ReportEngineJFree.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-09 11:56:15 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_REPORT_XREPORTENGINE_HPP_
#include <com/sun/star/report/XReportEngine.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef INCLUDED_CPPUHELPER_PROPERTYSETMIXIN_HXX
#include <cppuhelper/propertysetmixin.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROWSET_HPP_
#include <com/sun/star/sdbc/XRowSet.hpp>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
#include <comphelper/implementationreference.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

namespace reportdesign
{
    typedef ::cppu::WeakComponentImplHelper2< com::sun::star::report::XReportEngine
                                             ,com::sun::star::lang::XServiceInfo> ReportEngineBase;
    typedef ::cppu::PropertySetMixin<com::sun::star::report::XReportEngine> ReportEnginePropertySet;

    class OReportEngineJFree : public comphelper::OMutexAndBroadcastHelper,
                    public ReportEngineBase,
                    public ReportEnginePropertySet
    {
        typedef ::std::multimap< ::rtl::OUString, ::com::sun::star::uno::Any , ::comphelper::UStringMixLess>            TComponentMap;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >        m_xContext;
        ::com::sun::star::uno::Reference< ::com::sun::star::report::XReportDefinition >     m_xReport;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet >                 m_xRowSet;
        ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator>         m_StatusIndicator;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >             m_xActiveConnection;
    private:
        OReportEngineJFree(const OReportEngineJFree&);
        OReportEngineJFree& operator=(const OReportEngineJFree&);
        template <typename T> void set(  const ::rtl::OUString& _sProperty
                                        ,const T& _Value
                                        ,T& _member)
        {
            BoundListeners l;
            {
                ::osl::MutexGuard aGuard(m_aMutex);
                prepareSet(_sProperty, ::com::sun::star::uno::makeAny(_member), ::com::sun::star::uno::makeAny(_Value), &l);
                _member = _Value;
            }
            l.notify();
        }

        /** transform the report defintion format into a jfree report format.
         *
         * \return The URL of the newly created file.
         */
        ::rtl::OUString transform();

        /** returns the file url for a new model
        *
        * \return The new file url.
        */
        ::rtl::OUString getNewOutputName();

        /** set the rowset properties.
        *
        */
        void setRowSetProperties();

        /** generates the order statement defined by the groups of the report
        *
        * \return the ORDER BY part
        */
        ::rtl::OUString getOrderStatement() const;
    protected:
        virtual ~OReportEngineJFree();
    public:
        typedef ::comphelper::ImplementationReference< OReportEngineJFree   ,::com::sun::star::report::XReportEngine,::com::sun::star::uno::XWeak > TReportEngine;

        OReportEngineJFree(const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& context);

        DECLARE_XINTERFACE( )
        // ::com::sun::star::lang::XServiceInfo
        virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);

        static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( ::com::sun::star::uno::RuntimeException );
        static ::rtl::OUString getImplementationName_Static(void) throw( ::com::sun::star::uno::RuntimeException );
        static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
            create(::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext);
        // com::sun::star::beans::XPropertySet
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

        // XReportEngine
            // Attributes
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::report::XReportDefinition > SAL_CALL getReportDefinition() throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL setReportDefinition( const ::com::sun::star::uno::Reference< ::com::sun::star::report::XReportDefinition >& _reportdefinition ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getActiveConnection() throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setActiveConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _activeconnection ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > SAL_CALL getStatusIndicator() throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL setStatusIndicator( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator >& _statusindicator ) throw (::com::sun::star::uno::RuntimeException) ;
            // Methods
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SAL_CALL createDocumentModel(  ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SAL_CALL createDocumentAlive( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _frame ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;
        virtual ::com::sun::star::util::URL SAL_CALL createDocument(  ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL interrupt(  ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;

        // XComponent
        virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL addEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener) throw(::com::sun::star::uno::RuntimeException)
        {
            cppu::WeakComponentImplHelperBase::addEventListener(aListener);
        }
        virtual void SAL_CALL removeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener) throw(::com::sun::star::uno::RuntimeException)
        {
            cppu::WeakComponentImplHelperBase::removeEventListener(aListener);
        }
    };
}
#endif //REPORTDESIGN_API_REPORTENGINEJFREE_HXX
<commit_msg>INTEGRATION: CWS rptchart01_DEV300 (1.2.70); FILE MERGED 2008/02/13 07:12:47 oj 1.2.70.2: #i85225# impl chart readhandler and oleproducer 2008/01/24 12:39:31 oj 1.2.70.1: #i85225# changes for chart<commit_after>#ifndef REPORTDESIGN_API_REPORTENGINEJFREE_HXX
#define REPORTDESIGN_API_REPORTENGINEJFREE_HXX
/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ReportEngineJFree.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-05 17:56:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_REPORT_XREPORTENGINE_HPP_
#include <com/sun/star/report/XReportEngine.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef INCLUDED_CPPUHELPER_PROPERTYSETMIXIN_HXX
#include <cppuhelper/propertysetmixin.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROWSET_HPP_
#include <com/sun/star/sdbc/XRowSet.hpp>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
#include <comphelper/implementationreference.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

namespace reportdesign
{
    typedef ::cppu::WeakComponentImplHelper2< com::sun::star::report::XReportEngine
                                             ,com::sun::star::lang::XServiceInfo> ReportEngineBase;
    typedef ::cppu::PropertySetMixin<com::sun::star::report::XReportEngine> ReportEnginePropertySet;

    class OReportEngineJFree : public comphelper::OMutexAndBroadcastHelper,
                    public ReportEngineBase,
                    public ReportEnginePropertySet
    {
        typedef ::std::multimap< ::rtl::OUString, ::com::sun::star::uno::Any , ::comphelper::UStringMixLess>            TComponentMap;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >        m_xContext;
        ::com::sun::star::uno::Reference< ::com::sun::star::report::XReportDefinition >     m_xReport;
        ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator>         m_StatusIndicator;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >             m_xActiveConnection;
    private:
        OReportEngineJFree(const OReportEngineJFree&);
        OReportEngineJFree& operator=(const OReportEngineJFree&);
        template <typename T> void set(  const ::rtl::OUString& _sProperty
                                        ,const T& _Value
                                        ,T& _member)
        {
            BoundListeners l;
            {
                ::osl::MutexGuard aGuard(m_aMutex);
                prepareSet(_sProperty, ::com::sun::star::uno::makeAny(_member), ::com::sun::star::uno::makeAny(_Value), &l);
                _member = _Value;
            }
            l.notify();
        }

        /** transform the report defintion format into a jfree report format.
         *
         * \return The URL of the newly created file.
         */
        ::rtl::OUString transform();

        /** returns the file url for a new model
        *
        * \return The new file url.
        */
        ::rtl::OUString getNewOutputName();

        /** generates the order statement defined by the groups of the report
        *
        * \return the ORDER BY part
        */
        ::rtl::OUString getOrderStatement() const;
    protected:
        // TODO: VirtualFunctionFinder: This is virtual function!
        //
        virtual ~OReportEngineJFree();
    public:
        typedef ::comphelper::ImplementationReference< OReportEngineJFree   ,::com::sun::star::report::XReportEngine,::com::sun::star::uno::XWeak > TReportEngine;

        OReportEngineJFree(const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& context);

        DECLARE_XINTERFACE( )
        // ::com::sun::star::lang::XServiceInfo
        virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);

        static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( ::com::sun::star::uno::RuntimeException );
        static ::rtl::OUString getImplementationName_Static(void) throw( ::com::sun::star::uno::RuntimeException );
        static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
            create(::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext);
        // com::sun::star::beans::XPropertySet
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

        // XReportEngine
            // Attributes
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::report::XReportDefinition > SAL_CALL getReportDefinition() throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL setReportDefinition( const ::com::sun::star::uno::Reference< ::com::sun::star::report::XReportDefinition >& _reportdefinition ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getActiveConnection() throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setActiveConnection( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _activeconnection ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > SAL_CALL getStatusIndicator() throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL setStatusIndicator( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator >& _statusindicator ) throw (::com::sun::star::uno::RuntimeException) ;
            // Methods
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SAL_CALL createDocumentModel(  ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SAL_CALL createDocumentAlive( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _frame ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;
        virtual ::com::sun::star::util::URL SAL_CALL createDocument(  ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL interrupt(  ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ;

        // XComponent
        virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL addEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener) throw(::com::sun::star::uno::RuntimeException)
        {
            cppu::WeakComponentImplHelperBase::addEventListener(aListener);
        }
        virtual void SAL_CALL removeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & aListener) throw(::com::sun::star::uno::RuntimeException)
        {
            cppu::WeakComponentImplHelperBase::removeEventListener(aListener);
        }
    };
}
#endif //REPORTDESIGN_API_REPORTENGINEJFREE_HXX
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkFFTWHalfHermitianToRealInverseFFTImageFilter_hxx
#define itkFFTWHalfHermitianToRealInverseFFTImageFilter_hxx

#include "itkFFTWHalfHermitianToRealInverseFFTImageFilter.h"
#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"
#include "itkMultiThreaderBase.h"

namespace itk
{

template <typename TInputImage, typename TOutputImage>
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::FFTWHalfHermitianToRealInverseFFTImageFilter()
{
#ifndef ITK_USE_CUFFTW
  m_PlanRigor = FFTWGlobalConfiguration::GetPlanRigor();
#endif
  this->DynamicMultiThreadingOn();
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()
{
  // Get pointers to the input and output.
  typename InputImageType::ConstPointer inputPtr = this->GetInput();
  typename OutputImageType::Pointer     outputPtr = this->GetOutput();

  if (!inputPtr || !outputPtr)
  {
    return;
  }

  // We don't have a nice progress to report, but at least this simple line
  // reports the beginning and the end of the process.
  ProgressReporter progress(this, 0, 1);

  // Allocate output buffer memory.
  outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
  outputPtr->Allocate();

  const InputSizeType  inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const OutputSizeType outputSize = outputPtr->GetLargestPossibleRegion().GetSize();

  // Figure out sizes.
  // Size of input and output aren't the same which is handled in the superclass,
  // sort of.
  // The input size and output size only differ in the fastest moving dimension.
  unsigned int totalOutputSize = 1;
  unsigned int totalInputSize = 1;

  for (unsigned i = 0; i < ImageDimension; i++)
  {
    totalOutputSize *= outputSize[i];
    totalInputSize *= inputSize[i];
  }

  typename FFTWProxyType::ComplexType * in;
  // The complex-to-real transform doesn't support the
  // FFTW_PRESERVE_INPUT flag at this time. So if the input can't be
  // destroyed, we have to copy the input data to a buffer before
  // running the IFFT.
  if (m_CanUseDestructiveAlgorithm)
  {
    // Ok, so lets use the input buffer directly, to save some memory.
    in = (typename FFTWProxyType::ComplexType *)inputPtr->GetBufferPointer();
  }
  else
  {
    // We must use a buffer where fftw can work and destroy what it wants.
    in = new typename FFTWProxyType::ComplexType[totalInputSize];
  }
  OutputPixelType *                out = outputPtr->GetBufferPointer();
  typename FFTWProxyType::PlanType plan;

  int sizes[ImageDimension];
  for (unsigned int i = 0; i < ImageDimension; i++)
  {
    sizes[(ImageDimension - 1) - i] = outputSize[i];
  }
  plan = FFTWProxyType::Plan_dft_c2r(ImageDimension,
                                     sizes,
                                     in,
                                     out,
                                     m_PlanRigor,
                                     MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
                                     !m_CanUseDestructiveAlgorithm);
  if (!m_CanUseDestructiveAlgorithm)
  {
    // complex<double> and double[2] types are compatible memory layouts.
    // The reinterpret_cast is used here to
    // make the "C" fftw libary compatible with the c++ complex<double>.
    std::copy_n(
      inputPtr->GetBufferPointer(), totalInputSize, reinterpret_cast<typename InputImageType::PixelType *>(in));
  }
  FFTWProxyType::Execute(plan);

  // Some cleanup.
  FFTWProxyType::DestroyPlan(plan);
  if (!m_CanUseDestructiveAlgorithm)
  {
    delete[] in;
  }
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(
  const OutputRegionType & outputRegionForThread)
{
  using IteratorType = ImageRegionIterator<OutputImageType>;
  unsigned long totalOutputSize = this->GetOutput()->GetRequestedRegion().GetNumberOfPixels();
  IteratorType  it(this->GetOutput(), outputRegionForThread);
  while (!it.IsAtEnd())
  {
    it.Set(it.Value() / totalOutputSize);
    ++it;
  }
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::UpdateOutputData(DataObject * output)
{
  // We need to catch that information now, because it is changed
  // later during the pipeline execution, and thus can't be grabbed in
  // GenerateData().
  m_CanUseDestructiveAlgorithm = this->GetInput()->GetReleaseDataFlag();
  Superclass::UpdateOutputData(output);
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::PrintSelf(std::ostream & os,
                                                                                Indent         indent) const
{
  Superclass::PrintSelf(os, indent);

#ifndef ITK_USE_CUFFTW
  os << indent << "PlanRigor: " << FFTWGlobalConfiguration::GetPlanRigorName(m_PlanRigor) << " (" << m_PlanRigor << ")"
     << std::endl;
#endif
}

template <typename TInputImage, typename TOutputImage>
SizeValueType
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::GetSizeGreatestPrimeFactor() const
{
  return FFTWProxyType::GREATEST_PRIME_FACTOR;
}

} // namespace itk
#endif // _itkFFTWHalfHermitianToRealInverseFFTImageFilter_hxx
<commit_msg>COMP: Preserve const qualifier for variable<commit_after>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkFFTWHalfHermitianToRealInverseFFTImageFilter_hxx
#define itkFFTWHalfHermitianToRealInverseFFTImageFilter_hxx

#include "itkFFTWHalfHermitianToRealInverseFFTImageFilter.h"
#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"
#include "itkMultiThreaderBase.h"

namespace itk
{

template <typename TInputImage, typename TOutputImage>
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::FFTWHalfHermitianToRealInverseFFTImageFilter()
{
#ifndef ITK_USE_CUFFTW
  m_PlanRigor = FFTWGlobalConfiguration::GetPlanRigor();
#endif
  this->DynamicMultiThreadingOn();
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()
{
  // Get pointers to the input and output.
  typename InputImageType::ConstPointer inputPtr = this->GetInput();
  typename OutputImageType::Pointer     outputPtr = this->GetOutput();

  if (!inputPtr || !outputPtr)
  {
    return;
  }

  // We don't have a nice progress to report, but at least this simple line
  // reports the beginning and the end of the process.
  ProgressReporter progress(this, 0, 1);

  // Allocate output buffer memory.
  outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
  outputPtr->Allocate();

  const InputSizeType  inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const OutputSizeType outputSize = outputPtr->GetLargestPossibleRegion().GetSize();

  // Figure out sizes.
  // Size of input and output aren't the same which is handled in the superclass,
  // sort of.
  // The input size and output size only differ in the fastest moving dimension.
  unsigned int totalOutputSize = 1;
  unsigned int totalInputSize = 1;

  for (unsigned i = 0; i < ImageDimension; i++)
  {
    totalOutputSize *= outputSize[i];
    totalInputSize *= inputSize[i];
  }

  // The complex-to-real transform doesn't support the
  // FFTW_PRESERVE_INPUT flag at this time. So if the input can't be
  // destroyed, we have to copy the input data to a buffer before
  // running the IFFT.
  typename FFTWProxyType::ComplexType * const in = [&]() -> typename FFTWProxyType::ComplexType *
  {
    if (m_CanUseDestructiveAlgorithm)
    {
      // Ok, so lets use the input buffer directly, to save some memory.
      return const_cast<typename FFTWProxyType::ComplexType *>(
        reinterpret_cast<const typename FFTWProxyType::ComplexType *>(inputPtr->GetBufferPointer()));
    }
    else
    {
      // We must use a buffer where fftw can work and destroy what it wants.
      return new typename FFTWProxyType::ComplexType[totalInputSize];
    }
  }
  ();
  OutputPixelType *                out = outputPtr->GetBufferPointer();
  typename FFTWProxyType::PlanType plan;

  int sizes[ImageDimension];
  for (unsigned int i = 0; i < ImageDimension; i++)
  {
    sizes[(ImageDimension - 1) - i] = outputSize[i];
  }
  plan = FFTWProxyType::Plan_dft_c2r(ImageDimension,
                                     sizes,
                                     in,
                                     out,
                                     m_PlanRigor,
                                     MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
                                     !m_CanUseDestructiveAlgorithm);
  if (!m_CanUseDestructiveAlgorithm)
  {
    // complex<double> and double[2] types are compatible memory layouts.
    // The reinterpret_cast is used here to
    // make the "C" fftw libary compatible with the c++ complex<double>.
    std::copy_n(
      inputPtr->GetBufferPointer(), totalInputSize, reinterpret_cast<typename InputImageType::PixelType *>(in));
  }
  FFTWProxyType::Execute(plan);

  // Some cleanup.
  FFTWProxyType::DestroyPlan(plan);
  if (!m_CanUseDestructiveAlgorithm)
  {
    delete[] in;
  }
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(
  const OutputRegionType & outputRegionForThread)
{
  using IteratorType = ImageRegionIterator<OutputImageType>;
  unsigned long totalOutputSize = this->GetOutput()->GetRequestedRegion().GetNumberOfPixels();
  IteratorType  it(this->GetOutput(), outputRegionForThread);
  while (!it.IsAtEnd())
  {
    it.Set(it.Value() / totalOutputSize);
    ++it;
  }
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::UpdateOutputData(DataObject * output)
{
  // We need to catch that information now, because it is changed
  // later during the pipeline execution, and thus can't be grabbed in
  // GenerateData().
  m_CanUseDestructiveAlgorithm = this->GetInput()->GetReleaseDataFlag();
  Superclass::UpdateOutputData(output);
}

template <typename TInputImage, typename TOutputImage>
void
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::PrintSelf(std::ostream & os,
                                                                                Indent         indent) const
{
  Superclass::PrintSelf(os, indent);

#ifndef ITK_USE_CUFFTW
  os << indent << "PlanRigor: " << FFTWGlobalConfiguration::GetPlanRigorName(m_PlanRigor) << " (" << m_PlanRigor << ")"
     << std::endl;
#endif
}

template <typename TInputImage, typename TOutputImage>
SizeValueType
FFTWHalfHermitianToRealInverseFFTImageFilter<TInputImage, TOutputImage>::GetSizeGreatestPrimeFactor() const
{
  return FFTWProxyType::GREATEST_PRIME_FACTOR;
}

} // namespace itk
#endif // _itkFFTWHalfHermitianToRealInverseFFTImageFilter_hxx
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE
#include <boost/test/included/unit_test.hpp>

#include "connected.hpp"

BOOST_FIXTURE_TEST_CASE( respond_with_an_unknown_rsp, unconnected )
{
    check_single_ll_control_pdu(
        { 0x03, 0x01, 0xff },
        {
            0x03, 0x02,
            0x07, 0xff
        },
        "respond_with_an_unknown_rsp"
    );
}

BOOST_FIXTURE_TEST_CASE( responding_in_feature_setup, unconnected )
{
}

BOOST_FIXTURE_TEST_CASE( respond_to_a_version_ind, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x06,
            0x0C,               // LL_VERSION_IND
            0x08,               // VersNr = Core Specification 4.2
            0x00, 0x02,         // CompId
            0x00, 0x00          // SubVersNr
        },
        {
            0x03, 0x06,
            0x0C,               // LL_VERSION_IND
            0x09,               // VersNr = Core Specification 5.0
            0x69, 0x02,         // CompId
            0x00, 0x00          // SubVersNr
        },
        "respond_to_a_version_ind"
    );
}

BOOST_FIXTURE_TEST_CASE( respond_to_a_ping, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x01,
            0x12                // LL_PING_REQ
        },
        {
            0x03, 0x01,
            0x13                // LL_PING_RSP
        },
        "respond_to_a_ping"
    );
}

BOOST_FIXTURE_TEST_CASE( starts_advertising_after_termination, unconnected )
{
    respond_to( 37, valid_connection_request_pdu );
    add_connection_event_respond(
        {
            0x03, 0x02,
            0x02, 0x12
        } );

    run();

    // the second advertising PDU is the response to the terminate PDU
    // and must happen much earlier than the supervision timeout
    BOOST_REQUIRE_GT( advertisings().size(), 1u );
    const auto& second_advertisment = advertisings()[ 1 ];

    BOOST_CHECK_LT( second_advertisment.on_air_time, bluetoe::link_layer::delta_time::msec( 50 ) );
}

BOOST_FIXTURE_TEST_CASE( do_not_respond_to_UNKNOWN_RSP, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x02,
            0x07,               // LL_UNKNOWN_RSP
            0x07                // request opcode
        },
        {
            0x01, 0x00
        },
        "do_not_respond_to_UNKNOWN_RSP"
    );
}

BOOST_FIXTURE_TEST_CASE( do_not_respond_to_UNKNOWN_RSP_even_if_broken, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x03,
            0x07,               // LL_UNKNOWN_RSP
            0x07,               // request opcode
            0xff                // additional byte
        },
        {
            0x01, 0x00
        },
        "do_not_respond_to_UNKNOWN_RSP"
    );
}
<commit_msg>add tests for Channel Map Update procedure<commit_after>#define BOOST_TEST_MODULE
#include <boost/test/included/unit_test.hpp>

#include "connected.hpp"

BOOST_FIXTURE_TEST_CASE( respond_with_an_unknown_rsp, unconnected )
{
    check_single_ll_control_pdu(
        { 0x03, 0x01, 0xff },
        {
            0x03, 0x02,
            0x07, 0xff
        },
        "respond_with_an_unknown_rsp"
    );
}

BOOST_FIXTURE_TEST_CASE( responding_in_feature_setup, unconnected )
{
}

BOOST_FIXTURE_TEST_CASE( respond_to_a_version_ind, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x06,
            0x0C,               // LL_VERSION_IND
            0x08,               // VersNr = Core Specification 4.2
            0x00, 0x02,         // CompId
            0x00, 0x00          // SubVersNr
        },
        {
            0x03, 0x06,
            0x0C,               // LL_VERSION_IND
            0x09,               // VersNr = Core Specification 5.0
            0x69, 0x02,         // CompId
            0x00, 0x00          // SubVersNr
        },
        "respond_to_a_version_ind"
    );
}

BOOST_FIXTURE_TEST_CASE( respond_to_a_ping, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x01,
            0x12                // LL_PING_REQ
        },
        {
            0x03, 0x01,
            0x13                // LL_PING_RSP
        },
        "respond_to_a_ping"
    );
}

BOOST_FIXTURE_TEST_CASE( starts_advertising_after_termination, unconnected )
{
    respond_to( 37, valid_connection_request_pdu );
    add_connection_event_respond(
        {
            0x03, 0x02,
            0x02, 0x12
        } );

    run();

    // the second advertising PDU is the response to the terminate PDU
    // and must happen much earlier than the supervision timeout
    BOOST_REQUIRE_GT( advertisings().size(), 1u );
    const auto& second_advertisment = advertisings()[ 1 ];

    BOOST_CHECK_LT( second_advertisment.on_air_time, bluetoe::link_layer::delta_time::msec( 50 ) );
}

BOOST_FIXTURE_TEST_CASE( do_not_respond_to_UNKNOWN_RSP, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x02,
            0x07,               // LL_UNKNOWN_RSP
            0x07                // request opcode
        },
        {
            0x01, 0x00
        },
        "do_not_respond_to_UNKNOWN_RSP"
    );
}

BOOST_FIXTURE_TEST_CASE( do_not_respond_to_UNKNOWN_RSP_even_if_broken, unconnected )
{
    check_single_ll_control_pdu(
        {
            0x03, 0x03,
            0x07,               // LL_UNKNOWN_RSP
            0x07,               // request opcode
            0xff                // additional byte
        },
        {
            0x01, 0x00
        },
        "do_not_respond_to_UNKNOWN_RSP"
    );
}

/*
 * Example from core spec Vol6, Part B, 5.1.2
 */
BOOST_FIXTURE_TEST_CASE( Channel_Map_Update_procedure, unconnected )
{
    respond_to( 37, valid_connection_request_pdu );

    ll_control_pdu(
        {
            0x01,                           // LL_CHANNEL_MAP_IND
            0xff, 0xf7, 0xff, 0xff, 0x1f,   // new channel map: all channels enabled except channel 11
            0x64, 0x00                      // Instance: 100dez
        }
    );

    ll_empty_pdus( 101 );

    run();

    BOOST_CHECK_EQUAL( connection_events()[ 99 ].channel, 1u );
    BOOST_CHECK_EQUAL( connection_events()[ 100 ].channel, 12u );
    BOOST_CHECK_EQUAL( connection_events()[ 101 ].channel, 21u );
}

BOOST_FIXTURE_TEST_CASE( Channel_Map_Update_procedure_With_Latency, unconnected )
{
    respond_to( 37, {
        0xc5, 0x22,                         // header
        0x3c, 0x1c, 0x62, 0x92, 0xf0, 0x48, // InitA: 48:f0:92:62:1c:3c (random)
        0x47, 0x11, 0x08, 0x15, 0x0f, 0xc0, // AdvA:  c0:0f:15:08:11:47 (random)
        0x5a, 0xb3, 0x9a, 0xaf,             // Access Address
        0x08, 0x81, 0xf6,                   // CRC Init
        0x03,                               // transmit window size
        0x0b, 0x00,                         // window offset
        0x18, 0x00,                         // interval (30ms)
        0x28, 0x00,                         // peripheral latency 40
        0x48, 0x01,                         // connection timeout (3280ms)
        0xff, 0xff, 0xff, 0xff, 0x1f,       // used channel map
        0xaa                                // hop increment and sleep clock accuracy (10 and 50ppm)
    } );

    ll_control_pdu(
        {
            0x01,                           // LL_CHANNEL_MAP_IND
            0xff, 0xf7, 0xff, 0xff, 0x1f,   // new channel map: all channels enabled except channel 11
            0x64, 0x00                      // Instance: 100dez
        }
    );

    ll_empty_pdus( 5 );

    run();

    // First event at instant 0; second at 41, third at 82; 4th at 100
    BOOST_CHECK_EQUAL( connection_events()[ 3 ].channel, 12u );
}
<|endoftext|>