#pragma once #include #include #include #include #include #include "port_base.hpp" #include "tuple.hpp" enum class module_type_e : uint32_t { STANDALONE, INCOMPOSITION, }; template class ModuleBase { public: ModuleBase(int32_t argc, char **argv, char **envp, const std::string &name) : mc_name_(name), mc_cli_args_({ .argc = argc, .argv = argv, .envp = envp, }) {} inline const auto &name() const { return mc_name_; } virtual const PortBase &port(const std::string &name) const = 0; virtual void run(void (*entry)(int32_t, char **, char **, const std::unordered_map *> &)) const = 0; protected: const auto &cli__() const { return mc_cli_args_; } private: const std::string mc_name_; const struct { int32_t argc; char **argv, **envp; } mc_cli_args_; }; template class Module : public ModuleBase>> { public: using port_data_type_t = std::tuple_element_t<0, std::tuple>; Module(int32_t argc, char **argv, char **envp, const std::string &name, zmq::context_t &zmq_ctx, std::tuple...> &&ports) : ModuleBase(argc, argv, envp, name), mc_ports_([&](std::index_sequence) { return std::make_tuple([&]() { using port_type_t = std::remove_cvref_t(ports))>; auto &port = std::get(ports); return std::make_tuple(port->name(), std::hash()(port->name()), std::forward(port)); }.template operator()()...); }(std::make_index_sequence{})) {} const PortBase &port(const std::string &name) const override { const PortBase *ret = nullptr; size_t hash = std::hash()(name); tp::for_each(mc_ports_, [&](const auto &p) { if (!ret) { const auto &[port_name, name_hash, port] = p; if (name == port_name) { ret = static_cast *>(port.get()); } } }); if (!ret) { throw std::runtime_error(fmt::format("Port with name '{}' not found in '{}' module\r\n", name, this->name())); } return *ret; } void run(void (*entry)(int32_t, char **, char **, const std::unordered_map *> &)) const override { entry(this->cli__().argc, this->cli__().argv, this->cli__().envp, [&](std::index_sequence) -> std::unordered_map *> { return {std::make_pair(std::get<0u>(std::get(ports_())), std::get<2u>(std::get(ports_())).get())...}; }(std::make_index_sequence>>{})); } private: inline const auto &ports_() const { return mc_ports_; } const std::tuple>...> mc_ports_; };