File indexing completed on 2024-12-15 05:02:06

0001 /*
0002     SPDX-FileCopyrightText: 2018 Ivan Čukić <ivan.cukic(at)kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #ifndef VOY_WRAPPERS_PROCESS_H
0008 #define VOY_WRAPPERS_PROCESS_H
0009 
0010 // STL
0011 #include <vector>
0012 #include <functional>
0013 
0014 // Self
0015 #include "../utils.h"
0016 #include "../traits.h"
0017 #include "../dsl/node_tags.h"
0018 #include "../engine/asio/process.h"
0019 
0020 namespace voy {
0021 
0022 using voy::utils::non_copyable;
0023 
0024 template <typename ValueHandler, typename... Args>
0025 class process_impl: public non_copyable {
0026 public:
0027     using node_category = dsl::source_node_tag;
0028 
0029     explicit process_impl(std::tuple<Args...> command,
0030                           ValueHandler handler = voy::utils::identity{})
0031         : m_command{std::move(command)}
0032         , m_handler{std::move(handler)}
0033     {
0034     }
0035 
0036     template <typename Cont>
0037     class node: non_copyable {
0038         voy_assert_value_type(Cont);
0039 
0040         template <typename F, typename G>
0041         struct composition {
0042             voy_assert_value_type(F);
0043             voy_assert_value_type(G);
0044 
0045             F f;
0046             G g;
0047 
0048             composition(F f, G g)
0049                 : f{std::move(f)}
0050                 , g{std::move(g)}
0051             {
0052             }
0053 
0054             template <typename T>
0055             decltype(auto) operator() (T&& value) const
0056             {
0057                 #define EVAL_F_G std::invoke(f, voy_fwd_invoke(g, value))
0058                 if constexpr (std::is_same_v<void, decltype(EVAL_F_G)>) {
0059                     EVAL_F_G;
0060                 } else {
0061                     return EVAL_F_G;
0062                 }
0063                 #undef EVAL_F_G
0064             }
0065 
0066             void init()
0067             {
0068                 f.init();
0069             }
0070 
0071             void notify_ended() const
0072             {
0073                 f.notify_ended();
0074             }
0075         };
0076 
0077     public:
0078         using value_type = decltype(std::declval<ValueHandler>()(std::string{}));
0079 
0080         node(Cont&& cont, ValueHandler&& handler, std::tuple<Args...> command)
0081             : m_process{
0082                 std::make_unique<voy::engine::asio::process<composition<Cont, ValueHandler>>>(
0083                     composition<Cont, ValueHandler>{std::move(cont), std::move(handler)},
0084                     std::move(command)
0085                 )
0086             }
0087         {
0088         }
0089 
0090         void init()
0091         {
0092             m_process->init_handler();
0093         }
0094 
0095     private:
0096         std::unique_ptr<
0097             voy::engine::asio::process<composition<Cont, ValueHandler>>> m_process;
0098     };
0099 
0100 
0101     template <typename Cont>
0102     auto with_continuation(Cont&& cont) &&
0103     {
0104         return node<Cont>(
0105                 voy_fwd(cont), std::move(m_handler), std::move(m_command));
0106     }
0107 
0108 private:
0109     std::tuple<Args...> m_command;
0110     ValueHandler m_handler;
0111 };
0112 
0113 template <typename Cmd, typename... Args>
0114 auto process(Cmd&& cmd, Args&&... args)
0115 {
0116     return process_impl(
0117         std::make_tuple(voy_fwd(cmd), voy_fwd(args)...),
0118         voy::utils::identity{});
0119 }
0120 
0121 template <typename Cmd, typename... Args>
0122 auto system_cmd(Cmd&& cmd, Args&&... args)
0123 {
0124     return process(boost::process::search_path(voy_fwd(cmd)), voy_fwd(args)...);
0125 }
0126 
0127 }
0128 
0129 #endif // include guard
0130