File indexing completed on 2025-01-18 09:50:14
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_PROCESS_ENVIRONMENT_HPP_
0008 #define BOOST_PROCESS_ENVIRONMENT_HPP_
0009
0010 #include <boost/process/detail/config.hpp>
0011 #include <boost/algorithm/string/split.hpp>
0012 #include <boost/algorithm/string/case_conv.hpp>
0013 #include <boost/iterator/transform_iterator.hpp>
0014 #include <boost/process/filesystem.hpp>
0015
0016 #if defined(BOOST_POSIX_API)
0017 #include <boost/process/detail/posix/environment.hpp>
0018 #elif defined(BOOST_WINDOWS_API)
0019 #include <boost/process/detail/windows/environment.hpp>
0020 #endif
0021
0022 namespace boost { namespace process {
0023
0024 namespace detail {
0025
0026 template<typename Char, typename Environment>
0027 struct const_entry
0028 {
0029 using value_type = Char ;
0030 using pointer = const value_type * ;
0031 using string_type = std::basic_string<value_type> ;
0032 using range = boost::iterator_range<pointer> ;
0033 using environment_t = Environment ;
0034
0035 std::vector<string_type> to_vector() const
0036 {
0037 if (_data == nullptr)
0038 return std::vector<string_type>();
0039 std::vector<string_type> data;
0040 auto str = string_type(_data);
0041 struct splitter
0042 {
0043 bool operator()(wchar_t w) const {return w == api::env_seperator<wchar_t>();}
0044 bool operator()(char c) const {return c == api::env_seperator<char> ();}
0045 } s;
0046 boost::split(data, _data, s);
0047 return data;
0048 }
0049 string_type to_string() const
0050 {
0051 if (_data != nullptr)
0052 return string_type(_data);
0053 else
0054 return string_type();
0055 }
0056 string_type get_name() const {return string_type(_name.begin(), _name.end());}
0057 explicit const_entry(string_type&& name, pointer data, environment_t & env_) :
0058 _name(std::move(name)), _data(data), _env(&env_) {}
0059
0060 explicit const_entry(string_type &&name, environment_t & env) :
0061 _name(std::move(name)), _data(nullptr), _env(&env) {}
0062 const_entry(const const_entry&) = default;
0063 const_entry& operator=(const const_entry&) = default;
0064
0065 void reload()
0066 {
0067 auto p = _env->find(_name);
0068 if (p == _env->end())
0069 _data = nullptr;
0070 else
0071 _data = p->_data;
0072 this->_env->reload();
0073
0074 }
0075 bool empty() const
0076 {
0077 return _data == nullptr;
0078 }
0079 protected:
0080 string_type _name;
0081 pointer _data;
0082 environment_t * _env;
0083 };
0084
0085 template<typename Char, typename Environment>
0086 struct entry : const_entry<Char, Environment>
0087 {
0088 using father = const_entry<Char, Environment>;
0089 using value_type = typename father::value_type;
0090 using string_type = typename father::string_type;
0091 using pointer = typename father::pointer;
0092 using environment_t = typename father::environment_t;
0093
0094 explicit entry(string_type&& name, pointer data, environment_t & env) :
0095 father(std::move(name), data, env) {}
0096
0097 explicit entry(string_type &&name, environment_t & env_) :
0098 father(std::move(name), env_) {}
0099
0100 entry(const entry&) = default;
0101 entry& operator=(const entry&) = default;
0102
0103 void assign(const string_type &value)
0104 {
0105 this->_env->set(this->_name, value);
0106 this->reload();
0107 }
0108 void assign(const std::vector<string_type> &value)
0109 {
0110 string_type data;
0111 for (auto &v : value)
0112 {
0113 if (&v != &value.front())
0114 data += api::env_seperator<value_type>();
0115 data += v;
0116 }
0117 this->_env->set(this->_name, data);
0118 this->reload();
0119
0120 }
0121 void assign(const std::initializer_list<string_type> &value)
0122 {
0123 string_type data;
0124 for (auto &v : value)
0125 {
0126 if (&v != &*value.begin())
0127 data += api::env_seperator<value_type>();
0128 data += v;
0129 }
0130 this->_env->set(this->_name, data);
0131 this->reload();
0132
0133 }
0134 void append(const string_type &value)
0135 {
0136 if (this->_data == nullptr)
0137 this->_env->set(this->_name, value);
0138 else
0139 {
0140 string_type st = this->_data;
0141 this->_env->set(this->_name, st + api::env_seperator<value_type>() + value);
0142 }
0143
0144
0145 this->reload();
0146
0147 }
0148 void clear()
0149 {
0150 this->_env->reset(this->_name);
0151 this->_env->reload();
0152 this->_data = nullptr;
0153 }
0154 entry &operator=(const string_type & value)
0155 {
0156 assign(value);
0157 return *this;
0158 }
0159 entry &operator=(const std::vector<string_type> & value)
0160 {
0161 assign(value);
0162 return *this;
0163 }
0164 entry &operator=(const std::initializer_list<string_type> & value)
0165 {
0166 assign(value);
0167 return *this;
0168 }
0169 entry &operator+=(const string_type & value)
0170 {
0171 append(value);
0172 return *this;
0173 }
0174
0175 };
0176
0177
0178
0179 template<typename Char, typename Environment>
0180 struct make_entry
0181 {
0182
0183 make_entry(const make_entry&) = default;
0184 make_entry& operator=(const make_entry&) = default;
0185
0186 Environment *env;
0187 make_entry(Environment & env) : env(&env) {};
0188 entry<Char, Environment> operator()(const Char* data) const
0189 {
0190 auto p = data;
0191 while ((*p != equal_sign<Char>()) && (*p != null_char<Char>()))
0192 p++;
0193 auto name = std::basic_string<Char>(data, p);
0194 p++;
0195
0196 return entry<Char, Environment>(std::move(name), p, *env);
0197 }
0198 };
0199
0200 template<typename Char, typename Environment>
0201 struct make_const_entry
0202 {
0203
0204 make_const_entry(const make_const_entry&) = default;
0205 make_const_entry& operator=(const make_const_entry&) = default;
0206
0207 Environment *env;
0208 make_const_entry(Environment & env) : env(&env) {};
0209 const_entry<Char, Environment> operator()(const Char* data) const
0210 {
0211 auto p = data;
0212 while ((*p != equal_sign<Char>()) && (*p != null_char<Char>()))
0213 p++;
0214 auto name = std::basic_string<Char>(data, p);
0215 p++;
0216
0217 return const_entry<Char, Environment>(std::move(name), p, *env);
0218 }
0219 };
0220
0221 }
0222
0223 #if !defined (BOOST_PROCESS_DOXYGEN)
0224
0225 template<typename Char, template <class> class Implementation = detail::api::basic_environment_impl>
0226 class basic_environment_impl : public Implementation<Char>
0227 {
0228 Char** _get_end() const
0229 {
0230 auto p = this->_env_impl;
0231 while (*p != nullptr)
0232 p++;
0233
0234 return p;
0235 }
0236 public:
0237 using string_type = std::basic_string<Char>;
0238 using implementation_type = Implementation<Char>;
0239 using base_type = basic_environment_impl<Char, Implementation>;
0240 using entry_maker = detail::make_entry<Char, base_type>;
0241 using entry_type = detail::entry <Char, base_type>;
0242 using const_entry_type = detail::const_entry <Char, const base_type>;
0243 using const_entry_maker = detail::make_const_entry<Char, const base_type>;
0244
0245 friend entry_type;
0246 friend const_entry_type;
0247
0248 using iterator = boost::transform_iterator< entry_maker, Char**, entry_type, entry_type>;
0249 using const_iterator = boost::transform_iterator<const_entry_maker, Char**, const_entry_type, const_entry_type>;
0250 using size_type = std::size_t;
0251
0252 iterator begin() {return iterator(this->_env_impl, entry_maker(*this));}
0253 const_iterator begin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));}
0254 const_iterator cbegin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));}
0255
0256 iterator end() {return iterator(_get_end(), entry_maker(*this));}
0257 const_iterator end() const {return const_iterator(_get_end(), const_entry_maker(*this));}
0258 const_iterator cend() const {return const_iterator(_get_end(), const_entry_maker(*this));}
0259
0260 iterator find( const string_type& key )
0261 {
0262 auto p = this->_env_impl;
0263 auto st1 = key + ::boost::process::detail::equal_sign<Char>();
0264 while (*p != nullptr)
0265 {
0266 const std::size_t len = std::char_traits<Char>::length(*p);
0267 if ((std::distance(st1.begin(), st1.end()) < len)
0268 && std::equal(st1.begin(), st1.end(), *p))
0269 break;
0270 p++;
0271 }
0272 return iterator(p, entry_maker(*this));
0273 }
0274 const_iterator find( const string_type& key ) const
0275 {
0276 auto p = this->_env_impl;
0277 auto st1 = key + ::boost::process::detail::equal_sign<Char>();
0278 while (*p != nullptr)
0279 {
0280 const std::size_t len = std::char_traits<Char>::length(*p);
0281 if ((std::distance(st1.begin(), st1.end()) < len)
0282 && std::equal(st1.begin(), st1.end(), *p))
0283 break;
0284 p++;
0285 }
0286 return const_iterator(p, const_entry_maker(*this));
0287 }
0288
0289 std::size_t count(const string_type & st) const
0290 {
0291 auto p = this->_env_impl;
0292 auto st1 = st + ::boost::process::detail::equal_sign<Char>();
0293 while (*p != nullptr)
0294 {
0295 const std::size_t len = std::char_traits<Char>::length(*p);
0296 if ((std::distance(st1.begin(), st1.end()) <
0297 static_cast<typename string_type::iterator::difference_type>(len))
0298 && std::equal(st1.begin(), st1.end(), *p))
0299 return 1u;
0300 p++;
0301 }
0302 return 0u;
0303 }
0304 void erase(const string_type & id)
0305 {
0306 implementation_type::reset(id);
0307 this->reload();
0308 }
0309 std::pair<iterator,bool> emplace(const string_type & id, const string_type & value)
0310 {
0311 auto f = find(id);
0312 if (f == end())
0313 {
0314 implementation_type::set(id, value);
0315 this->reload();
0316 return std::pair<iterator, bool>(find(id), true);
0317 }
0318 else
0319 return std::pair<iterator, bool>(f, false);
0320 }
0321 using implementation_type::implementation_type;
0322 using implementation_type::operator=;
0323 using native_handle_type = typename implementation_type::native_handle_type;
0324 using implementation_type::native_handle;
0325
0326 bool empty()
0327 {
0328 return *this->_env_impl == nullptr;
0329 }
0330 std::size_t size() const
0331 {
0332 return (_get_end() - this->_env_impl);
0333 }
0334 void clear()
0335 {
0336 std::vector<string_type> names;
0337 names.resize(size());
0338 std::transform(cbegin(), cend(), names.begin(), [](const const_entry_type & cet){return cet.get_name();});
0339
0340 for (auto & nm : names)
0341 implementation_type::reset(nm);
0342
0343 this->reload();
0344 }
0345
0346 entry_type at( const string_type& key )
0347 {
0348 auto f = find(key);
0349 if (f== end())
0350 throw std::out_of_range(key + " not found");
0351 return *f;
0352 }
0353 const_entry_type at( const string_type& key ) const
0354 {
0355 auto f = find(key);
0356 if (f== end())
0357 throw std::out_of_range(key + " not found");
0358 return *f;
0359 }
0360 entry_type operator[](const string_type & key)
0361 {
0362 auto p = find(key);
0363 if (p != end())
0364 return *p;
0365
0366 return entry_type(string_type(key), *this);
0367 }
0368 };
0369 #endif
0370
0371 #if defined(BOOST_PROCESS_DOXYGEN)
0372
0373
0374
0375 template<typename Char>
0376 class basic_environment
0377 {
0378
0379 public:
0380 typedef std::basic_string<Char> string_type;
0381 typedef boost::transform_iterator< entry_maker, Char**> iterator ;
0382 typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ;
0383 typedef std::size_t size_type ;
0384
0385 iterator begin() ;
0386 const_iterator begin() const ;
0387 const_iterator cbegin() const ;
0388
0389 iterator end() ;
0390 const_iterator end() const;
0391 const_iterator cend() const;
0392
0393 iterator find( const string_type& key );
0394 const_iterator find( const string_type& key ) const;
0395
0396 std::size_t count(const string_type & st) const;
0397 void erase(const string_type & id);
0398
0399 std::pair<iterator,bool> emplace(const string_type & id, const string_type & value);
0400
0401
0402 basic_environment();
0403
0404 basic_environment(const basic_environment & );
0405
0406 basic_environment(basic_environment && );
0407
0408
0409 basic_environment& operator=(const basic_environment & );
0410
0411 basic_environment& operator=(basic_environment && );
0412
0413 typedef typename detail::implementation_type::native_handle_type native_handle;
0414
0415
0416 bool empty();
0417
0418 std::size_t size() const;
0419
0420 void clear();
0421
0422 entry_type at( const string_type& key );
0423
0424 const_entry_type at( const string_type& key ) const;
0425
0426 entry_type operator[](const string_type & key);
0427
0428
0429
0430
0431 template<typename Char, typename Environment>
0432 struct const_entry_type
0433 {
0434 typedef Char value_type;
0435 typedef const value_type * pointer;
0436 typedef std::basic_string<value_type> string_type;
0437 typedef boost::iterator_range<pointer> range;
0438 typedef Environment environment_t;
0439
0440
0441 std::vector<string_type> to_vector() const
0442
0443 string_type to_string() const
0444
0445 string_type get_name() const {return string_type(_name.begin(), _name.end());}
0446
0447 const_entry(const const_entry&) = default;
0448
0449 const_entry& operator=(const const_entry&) = default;
0450
0451 bool empty() const;
0452 };
0453
0454
0455
0456
0457 template<typename Char, typename Environment>
0458 struct entry_type
0459 {
0460
0461 typedef Char value_type;
0462 typedef const value_type * pointer;
0463 typedef std::basic_string<value_type> string_type;
0464 typedef boost::iterator_range<pointer> range;
0465 typedef Environment environment_t;
0466
0467
0468 std::vector<string_type> to_vector() const
0469
0470 string_type to_string() const
0471
0472 string_type get_name() const {return string_type(_name.begin(), _name.end());}
0473
0474 entry(const entry&) = default;
0475
0476 entry& operator=(const entry&) = default;
0477
0478 bool empty() const;
0479
0480
0481 void assign(const string_type &value);
0482
0483 void assign(const std::vector<string_type> &value);
0484
0485 void append(const string_type &value);
0486
0487 void clear();
0488
0489 entry &operator=(const string_type & value);
0490
0491 entry &operator=(const std::vector<string_type> & value);
0492
0493 entry &operator+=(const string_type & value);
0494 };
0495
0496 };
0497
0498
0499
0500
0501
0502 template<typename Char>
0503 class basic_native_environment
0504 {
0505
0506 public:
0507 typedef std::basic_string<Char> string_type;
0508 typedef boost::transform_iterator< entry_maker, Char**> iterator ;
0509 typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ;
0510 typedef std::size_t size_type ;
0511
0512 iterator begin() ;
0513 const_iterator begin() const ;
0514 const_iterator cbegin() const ;
0515
0516 iterator end() ;
0517 const_iterator end() const;
0518 const_iterator cend() const;
0519
0520 iterator find( const string_type& key );
0521 const_iterator find( const string_type& key ) const;
0522
0523 std::size_t count(const string_type & st) const;
0524 void erase(const string_type & id);
0525
0526 std::pair<iterator,bool> emplace(const string_type & id, const string_type & value);
0527
0528
0529 basic_native_environment();
0530
0531 basic_native_environment(basic_native_environment && );
0532
0533 basic_native_environment& operator=(basic_native_environment && );
0534
0535 typedef typename detail::implementation_type::native_handle_type native_handle;
0536
0537
0538 bool empty();
0539
0540 std::size_t size() const;
0541
0542 entry_type at( const string_type& key );
0543
0544 const_entry_type at( const string_type& key ) const;
0545
0546 entry_type operator[](const string_type & key);
0547
0548
0549
0550
0551 template<typename Char, typename Environment>
0552 struct const_entry_type
0553 {
0554 typedef Char value_type;
0555 typedef const value_type * pointer;
0556 typedef std::basic_string<value_type> string_type;
0557 typedef boost::iterator_range<pointer> range;
0558 typedef Environment environment_t;
0559
0560
0561 std::vector<string_type> to_vector() const
0562
0563 string_type to_string() const
0564
0565 string_type get_name() const {return string_type(_name.begin(), _name.end());}
0566
0567 const_entry(const const_entry&) = default;
0568
0569 const_entry& operator=(const const_entry&) = default;
0570
0571 bool empty() const;
0572 };
0573
0574
0575
0576
0577 template<typename Char, typename Environment>
0578 struct entry_type
0579 {
0580
0581 typedef Char value_type;
0582 typedef const value_type * pointer;
0583 typedef std::basic_string<value_type> string_type;
0584 typedef boost::iterator_range<pointer> range;
0585 typedef Environment environment_t;
0586
0587
0588 std::vector<string_type> to_vector() const
0589
0590 string_type to_string() const
0591
0592 string_type get_name() const {return string_type(_name.begin(), _name.end());}
0593
0594 entry(const entry&) = default;
0595
0596 entry& operator=(const entry&) = default;
0597
0598 bool empty() const;
0599
0600
0601 void assign(const string_type &value);
0602
0603 void assign(const std::vector<string_type> &value);
0604
0605 void append(const string_type &value);
0606
0607 void clear();
0608
0609 entry &operator=(const string_type & value);
0610
0611 entry &operator=(const std::vector<string_type> & value);
0612
0613 entry &operator+=(const string_type & value);
0614 };
0615
0616 };
0617
0618 #endif
0619
0620
0621 template<typename Char>
0622 class basic_native_environment : public basic_environment_impl<Char, detail::api::native_environment_impl>
0623 {
0624 public:
0625 using base_type = basic_environment_impl<Char, detail::api::native_environment_impl>;
0626 using base_type::base_type;
0627 using base_type::operator=;
0628 };
0629
0630
0631 template<typename Char>
0632 class basic_environment : public basic_environment_impl<Char, detail::api::basic_environment_impl>
0633 {
0634 public:
0635 using base_type = basic_environment_impl<Char, detail::api::basic_environment_impl>;
0636 using base_type::base_type;
0637 using base_type::operator=;
0638 };
0639
0640
0641 #if !defined(BOOST_NO_ANSI_APIS)
0642
0643 typedef basic_native_environment<char> native_environment;
0644 #endif
0645
0646 typedef basic_native_environment<wchar_t> wnative_environment;
0647
0648 #if !defined(BOOST_NO_ANSI_APIS)
0649
0650 typedef basic_environment<char> environment;
0651 #endif
0652
0653 typedef basic_environment<wchar_t> wenvironment;
0654
0655 }
0656
0657
0658 namespace this_process
0659 {
0660
0661
0662 typedef ::boost::process::detail::api::native_handle_t native_handle_type;
0663
0664 #if !defined(BOOST_NO_ANSI_APIS)
0665
0666 using ::boost::process::native_environment;
0667 #endif
0668
0669 using ::boost::process::wnative_environment;
0670
0671
0672 inline int get_id() { return ::boost::process::detail::api::get_id();}
0673
0674 inline native_handle_type native_handle() { return ::boost::process::detail::api::native_handle();}
0675 #if !defined(BOOST_NO_ANSI_APIS)
0676
0677 inline native_environment environment() { return ::boost::process:: native_environment(); }
0678 #endif
0679
0680 inline wnative_environment wenvironment() { return ::boost::process::wnative_environment(); }
0681
0682 inline std::vector<boost::process::filesystem::path> path()
0683 {
0684 #if defined(BOOST_WINDOWS_API)
0685 const ::boost::process::wnative_environment ne{};
0686 typedef typename ::boost::process::wnative_environment::const_entry_type value_type;
0687 static constexpr auto id = L"PATH";
0688 #else
0689 const ::boost::process::native_environment ne{};
0690 typedef typename ::boost::process::native_environment::const_entry_type value_type;
0691 static constexpr auto id = "PATH";
0692 #endif
0693
0694 auto itr = std::find_if(ne.cbegin(), ne.cend(),
0695 [&](const value_type & e)
0696 {return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());});
0697
0698 if (itr == ne.cend())
0699 return {};
0700
0701 auto vec = itr->to_vector();
0702
0703 std::vector<boost::process::filesystem::path> val;
0704 val.resize(vec.size());
0705
0706 std::copy(vec.begin(), vec.end(), val.begin());
0707
0708 return val;
0709 }
0710 }
0711 }
0712 #endif