Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:58:03

0001 // Copyright (c) 2016 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_PROCESS_DETAIL_ENV_HPP_
0007 #define BOOST_PROCESS_DETAIL_ENV_HPP_
0008 
0009 #include <boost/process/detail/traits/wchar_t.hpp>
0010 #include <boost/process/environment.hpp>
0011 #include <boost/none.hpp>
0012 
0013 #if defined(BOOST_POSIX_API)
0014 #include <boost/process/detail/posix/env_init.hpp>
0015 #elif defined(BOOST_WINDOWS_API)
0016 #include <boost/process/detail/windows/env_init.hpp>
0017 #endif
0018 
0019 /** \file boost/process/env.hpp
0020  *
0021  *    This header which provides the `env` property. It allows the modification of the
0022  *    environment the child process will run in, in a functional style.
0023  *
0024  *  \xmlonly
0025 <programlisting>
0026 namespace boost {
0027   namespace process {
0028     <emphasis>unspecified</emphasis> <globalname alt="boost::process::env">env</globalname>;
0029   }
0030 }
0031 </programlisting>
0032  *  \endxmlonly
0033  *
0034  *  For additional information see the platform documentations:
0035  *
0036  *   - [windows](https://msdn.microsoft.com/en-US/library/windows/desktop/ms682653.aspx)
0037  *   - [posix](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
0038  *
0039  */
0040 
0041 
0042 namespace boost {
0043 
0044 namespace process { namespace detail {
0045 
0046 
0047 template<typename Char>
0048 std::size_t make_env_string_size(const std::basic_string<Char> & ch)
0049 {
0050     return ch.size() + 1;
0051 }
0052 
0053 template<typename Char>
0054 std::size_t make_env_string_size(const Char * ch)
0055 {
0056     std::size_t sz = 0;
0057     while (ch[sz] != null_char<Char>())
0058         sz++;
0059 
0060     sz++;
0061     return sz;
0062 }
0063 
0064 template<typename Char, typename Container>
0065 inline std::basic_string<Char> make_env_string(const Container & value)
0066 {
0067     std::size_t sz = 0;
0068     for (auto & v : value)
0069         sz += make_env_string_size(v);
0070 
0071     std::basic_string<Char> s;
0072     s.reserve(sz); //+1 for ;, end doesn't have one.
0073 
0074     for (auto & val : value)
0075         (s += val) += api::env_seperator<Char>();
0076 
0077     s.resize(s.size() -1); //remove last ';'
0078     return s;
0079 }
0080 
0081 
0082 template<typename Char>
0083 struct env_set
0084 {
0085     using string_type = std::basic_string<Char>;
0086     string_type key;
0087     string_type value;
0088 };
0089 
0090 template<typename Char>
0091 struct env_append
0092 {
0093     using string_type = std::basic_string<Char>;
0094     string_type key;
0095     string_type value;
0096 };
0097 
0098 
0099 
0100 template<typename Char>
0101 struct env_reset
0102 {
0103     using string_type = std::basic_string<Char>;
0104     string_type key;
0105 };
0106 
0107 
0108 template<> struct is_wchar_t<env_set<wchar_t>>           : std::true_type {};
0109 template<> struct is_wchar_t<env_append<wchar_t>>        : std::true_type {};
0110 template<> struct is_wchar_t<env_reset<wchar_t>>         : std::true_type {};
0111 template<> struct is_wchar_t<basic_environment<wchar_t>> : std::true_type {};
0112 
0113 
0114 template<>
0115 struct char_converter<char, env_set<wchar_t>>
0116 {
0117     static env_set<char> conv(const env_set<wchar_t> & in)
0118     {
0119         return {::boost::process::detail::convert(in.key),
0120                 ::boost::process::detail::convert(in.value)};
0121     }
0122 };
0123 
0124 template<>
0125 struct char_converter<wchar_t, env_set<char>>
0126 {
0127     static env_set<wchar_t> conv(const env_set<char> & in)
0128     {
0129         return {::boost::process::detail::convert(in.key),
0130                 ::boost::process::detail::convert(in.value)};
0131     }
0132 };
0133 
0134 template<>
0135 struct char_converter<char, env_append<wchar_t>>
0136 {
0137     static env_append<char> conv(const env_append<wchar_t> & in)
0138     {
0139         return {::boost::process::detail::convert(in.key),
0140                 ::boost::process::detail::convert(in.value)};
0141     }
0142 };
0143 
0144 template<>
0145 struct char_converter<wchar_t, env_append<char>>
0146 {
0147     static env_append<wchar_t> conv(const env_append<char> & in)
0148     {
0149         return {::boost::process::detail::convert(in.key),
0150                 ::boost::process::detail::convert(in.value)};
0151     }
0152 };
0153 
0154 template<>
0155 struct char_converter<char, env_reset<wchar_t>>
0156 {
0157     static env_reset<char> conv(const env_reset<wchar_t> & in)
0158     {
0159         return {::boost::process::detail::convert(in.key)};
0160     }
0161 };
0162 
0163 template<>
0164 struct char_converter<wchar_t, env_reset<char>>
0165 {
0166     static env_reset<wchar_t> conv(const env_reset<char> & in)
0167     {
0168         return {::boost::process::detail::convert(in.key)};
0169     }
0170 };
0171 
0172 
0173 template<typename Char>
0174 struct env_init
0175 {
0176     basic_environment<Char> env;
0177 };
0178 
0179 template<>
0180 struct char_converter<char, env_init<wchar_t>>
0181 {
0182     static env_init<char> conv(const env_init<wchar_t> & in)
0183     {
0184         return {basic_environment<char>(in.env)};
0185     }
0186 };
0187 
0188 template<>
0189 struct char_converter<wchar_t, env_init<char>>
0190 {
0191     static env_init<wchar_t> conv(const env_init<char> & in)
0192     {
0193         return {basic_environment<wchar_t>(in.env)};
0194     }
0195 };
0196 
0197 template<>
0198 struct char_converter<char, basic_environment<wchar_t>>
0199 {
0200     static basic_environment<char> conv(const basic_environment<wchar_t> & in)
0201     {
0202         return { basic_environment<char>(in) };
0203     }
0204 };
0205 
0206 template<>
0207 struct char_converter<wchar_t, basic_environment<char>>
0208 {
0209     static basic_environment<wchar_t> conv(const basic_environment<char> & in)
0210     {
0211         return { basic_environment<wchar_t>(in) };
0212     }
0213 };
0214 
0215 template<typename Char>
0216 struct env_proxy
0217 {
0218     using string_type = std::basic_string<Char>;
0219     string_type key;
0220 
0221 
0222     env_set<Char> operator=(const string_type & value)
0223     {
0224         return {std::move(key), value};
0225     }
0226     env_set<Char> operator=(const std::vector<string_type> & value)
0227     {
0228         return {std::move(key), make_env_string<Char>(value)};
0229     }
0230     env_set<Char> operator=(const std::initializer_list<const Char*> & value)
0231     {
0232         return {std::move(key), make_env_string<Char>(value)};
0233     }
0234 
0235     env_append<Char> operator+=(const string_type & value)
0236     {
0237         return {std::move(key), value};
0238     }
0239     env_append<Char> operator+=(const std::vector<string_type> & value)
0240     {
0241         return {std::move(key), make_env_string<Char>(value)};
0242     }
0243     env_append<Char> operator+=(const std::initializer_list<const Char*> & value)
0244     {
0245         return {std::move(key), make_env_string<Char>(value)};
0246     }
0247     env_reset<Char> operator=(boost::none_t)
0248     {
0249         return {std::move(key)};
0250     }
0251 };
0252 
0253 struct env_
0254 {
0255     constexpr env_() {};
0256 
0257     template<typename Char>
0258     env_set<Char> operator()(const std::basic_string<Char> & key,
0259                              const std::basic_string<Char> & value) const
0260     {
0261         return {key, value};
0262     }
0263     template<typename Char>
0264     env_set<Char> operator()(const std::basic_string<Char> & key,
0265                                 const std::vector<std::basic_string<Char>> & value) const
0266     {
0267         return {key, make_env_string<Char>(value)};
0268     }
0269     template<typename Char>
0270     env_set<Char> operator()(const std::basic_string<Char> & key,
0271                              const std::initializer_list<Char*> & value) const
0272     {
0273         return {key, make_env_string<Char>(value)};
0274     }
0275     template<typename Char>
0276     env_reset<Char> operator()(const std::basic_string<Char> & key, boost::none_t)
0277     {
0278         return {key};
0279     }
0280     template<typename Char>
0281     env_proxy<Char> operator[](const std::basic_string<Char> & key) const
0282     {
0283         return {key};
0284     }
0285     template<typename Char>
0286     env_proxy<Char> operator[](const Char* key) const
0287     {
0288         return {key};
0289     }
0290     template<typename Char>
0291     env_init<Char> operator()(const basic_environment<Char> & env) const
0292     {
0293         return {env};
0294     }
0295     template<typename Char>
0296     env_init<Char> operator= (const basic_environment<Char> & env) const
0297     {
0298         return {env};
0299     }
0300 };
0301 
0302 template<typename Char>
0303 struct env_builder
0304 {
0305     basic_environment<Char> env;
0306     env_builder() : env{basic_native_environment<Char>()} {}
0307 
0308     void operator()(const basic_environment<Char> & e)
0309     {
0310         env = e;
0311     }
0312 
0313     void operator()(env_init<Char> & ei)
0314     {
0315         env = std::move(ei.env);
0316     }
0317     void operator()(env_set<Char> & es)
0318     {
0319         env[es.key] = es.value;
0320     }
0321     void operator()(env_reset<Char> & es)
0322     {
0323         env.erase(es.key);
0324     }
0325     template<typename T>
0326     void operator()(env_append<T> & es)
0327     {
0328         env[es.key] += es.value;
0329     }
0330 
0331     typedef api::env_init<Char> result_type;
0332     api::env_init<Char> get_initializer()
0333     {
0334         return api::env_init<Char>(std::move(env));
0335     }
0336 };
0337 
0338 template<>
0339 struct initializer_builder<env_tag<char>>
0340 {
0341     typedef env_builder<char> type;
0342 };
0343 
0344 template<>
0345 struct initializer_builder<env_tag<wchar_t>>
0346 {
0347     typedef env_builder<wchar_t> type;
0348 };
0349 
0350 }
0351 
0352 /**
0353 
0354 The `env` property provides a functional way to modify the environment used by
0355 the child process. If none is passed the environment is inherited from the father
0356 process. Appending means that the environment will be interpreted as a ';' or ':'
0357 separated list as used in `PATH`.
0358 
0359 On both `posix` and `windows` the environment variables can be lists of strings,
0360 separated by ';'. This is typically used for the `PATH` variable.
0361 
0362 By default the environment will be inherited from the launching process,
0363 which is also true if environment are modified with this initializer.
0364 
0365 \section env_details Details
0366 
0367 \subsection env_operations Operations
0368 
0369 \subsubsection env_set_var Setting variables
0370 
0371 To set a variable `id` the value `value` the following syntax can be used.
0372 
0373 \code{.cpp}
0374 env[id] = value;
0375 env(id, value);
0376 \endcode
0377 
0378 `std::initializer_list` is among the allowed types, so the following syntax is also possible.
0379 
0380 \code{.cpp}
0381 env[id] = {value1, value2};
0382 env(id, {value1, value2});
0383 \endcode
0384 
0385 \note Creates the variable if it does not exist.
0386 
0387 The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
0388 for both `id` and `value`.
0389 
0390 \paragraph id id
0391 
0392  - `std::basic_string<char_type>`
0393  - `const char_type *`
0394 
0395 \paragraph env_set_var_value value
0396 
0397  - `std::basic_string<char_type>`
0398  - `const char_type * `
0399  - `std::initializer_list<const char_type *>`
0400  - `std::vector<std::basic_string<char_type>>`
0401 
0402 
0403 \note Using `std::vector` or `std::initializer_list`
0404 
0405 \subsubsection env_append_var Append variables
0406 
0407 Appending means, that a variable will be interpreted as a
0408 To append  a variable `id` the value `value` the following syntax can be used:
0409 
0410 \code{.cpp}
0411 env[id] += value;
0412 \endcode
0413 
0414 `std::initializer_list` is among the allowed types, so the following syntax is also possible.
0415 
0416 \code{.cpp}
0417 env[id] += {value1, value2};
0418 \endcode
0419 
0420 \note Creates the variable if it does not exist.
0421 
0422 The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
0423 for both `id` and `value`.
0424 
0425 \paragraph env_append_var_id id
0426 
0427  - `std::basic_string<char_type>`
0428  - `const char_type *`
0429 
0430 \paragraph env_append_var_value value
0431 
0432  - `std::basic_string<char_type>`
0433  - `const char_type *`
0434  - `std::initializer_list<const char_type *>`
0435  - `std::vector<std::basic_string<char_type>>`
0436 
0437 
0438 \subsubsection env_reset Reset variables
0439 
0440 Resetting single variables can be done in the following way:
0441 
0442 \code{.cpp}
0443 env[id] = boost::none;
0444 env(id, boost::none);
0445 \endcode
0446 
0447 \note This does not set the value empty, but removes it from the list.
0448 
0449 The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`:
0450 
0451 \paragraph env_reset_var_id id
0452 
0453  - `std::basic_string<char_type>`
0454  - `const char_type *`
0455 
0456 \subsubsection env_init Initialize the environment
0457 
0458 The whole environment can be initialized from an object of type
0459 \xmlonly <classname>boost::process::environment</classname> \endxmlonly
0460 
0461 \code{.cpp}
0462 env=env;
0463 env(env);
0464 \endcode
0465 
0466 \note The passed `environment` can also be default-constructed to get an empty environment.
0467 
0468 \paragraph env_init_var_id id
0469 
0470  - `std::basic_string<char_type>`
0471  - `const char_type *`
0472 
0473 \paragraph env_init_var_value value
0474 
0475  - `boost::process::basic_environment<char_type>`
0476 
0477 \subsection env_example Example
0478 
0479 \code{.cpp}
0480 spawn("b2", env["PATH"]+="F:/boost", env["SOME_VAR"]=boost::none, env["NEW_VAR"]="VALUE");
0481 \endcode
0482 
0483 If the overload style should be done by passing an instance of
0484 \xmlonly <classname>boost::process::environment</classname> \endxmlonly
0485 the above example would look like this.
0486 
0487 \code{.cpp}
0488 environment e = this_process::environment();
0489 e["PATH"]   += "F:/boost";
0490 e.erase("SOME_VAR");
0491 e["NEW_VAR"] = "VALUE";
0492 spawn("b2", e);
0493 \endcode
0494 
0495 \warning Passing an empty environment will cause undefined behaviour.
0496 
0497  */
0498 constexpr boost::process::detail::env_ env{};
0499 
0500 
0501 }}
0502 
0503 #endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */