File indexing completed on 2025-07-11 08:25:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_PROCESS_V2_ENVIRONMENT_HPP
0011 #define BOOST_PROCESS_V2_ENVIRONMENT_HPP
0012
0013 #include <boost/process/v2/detail/config.hpp>
0014 #include <boost/process/v2/cstring_ref.hpp>
0015 #include <boost/process/v2/detail/utf8.hpp>
0016
0017 #include <boost/type_traits.hpp>
0018
0019 #include <functional>
0020 #include <memory>
0021 #include <numeric>
0022 #include <vector>
0023
0024 #if !defined(GENERATING_DOCUMENTATION)
0025 #if defined(BOOST_PROCESS_V2_WINDOWS)
0026 #include <boost/process/v2/detail/environment_win.hpp>
0027 #else
0028 #include <boost/process/v2/detail/environment_posix.hpp>
0029 #endif
0030 #endif
0031
0032 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0033
0034
0035 namespace environment
0036 {
0037
0038 #if defined(GENERATING_DOCUMENTATION)
0039
0040
0041
0042
0043
0044
0045
0046 tempalte<typename Char>
0047 using key_char_traits = implementation_defined ;
0048
0049
0050
0051
0052 tempalte<typename Char>
0053 using value_char_traits = implementation_defined ;
0054
0055
0056 using char_type = implementation_defined ;
0057
0058
0059 constexpr char_type equality_sign = implementation_defined;
0060
0061
0062 constexpr char_type delimiter = implementation_defined;
0063
0064
0065 using native_handle = implementation_defined;
0066
0067
0068 #endif
0069
0070
0071
0072 struct value_iterator
0073 {
0074 using string_view_type = basic_string_view<char_type, value_char_traits<char_type>>;
0075 using difference_type = int;
0076 using reference = string_view_type;
0077 using iterator_category = std::forward_iterator_tag;
0078
0079 value_iterator & operator++()
0080 {
0081 const auto delim = view_.find(delimiter);
0082 if (delim != string_view_type::npos)
0083 view_ = view_.substr(delim + 1);
0084 else
0085 view_ = view_.substr(view_.size());
0086 return *this;
0087 }
0088
0089 value_iterator operator++(int)
0090 {
0091 auto last = *this;
0092 ++(*this);
0093 return last;
0094 }
0095 string_view_type operator*() const
0096 {
0097 const auto delim = view_.find(delimiter);
0098 if (delim == string_view_type::npos)
0099 return view_;
0100 else
0101 return view_.substr(0, delim);
0102 }
0103
0104 value_iterator() = default;
0105 value_iterator(const value_iterator & ) = default;
0106 value_iterator(string_view_type view, std::size_t offset = 0u) : view_(view.substr(offset))
0107 {
0108 }
0109
0110 friend bool operator==(const value_iterator & l, const value_iterator & r) { return l.view_ == r.view_; }
0111 friend bool operator!=(const value_iterator & l, const value_iterator & r) { return l.view_ != r.view_; }
0112
0113 private:
0114 string_view_type view_;
0115 };
0116
0117
0118 struct key_view
0119 {
0120 using value_type = char_type;
0121 using traits_type = key_char_traits<char_type>;
0122 using string_view_type = basic_string_view<char_type, traits_type>;
0123 using string_type = std::basic_string<char_type, key_char_traits<char_type>>;
0124
0125 key_view() noexcept = default;
0126 key_view( const key_view& p ) = default;
0127 key_view( key_view&& p ) noexcept = default;
0128 template<typename Source,
0129 typename = typename std::enable_if<is_constructible<string_view_type, Source>::value>::type>
0130 key_view( const Source& source ) : value_(source) {}
0131 key_view( const char_type * p) : value_(p) {}
0132 key_view( char_type * p) : value_(p) {}
0133
0134 ~key_view() = default;
0135
0136 key_view& operator=( const key_view& p ) = default;
0137 key_view& operator=( key_view&& p ) noexcept = default;
0138 key_view& operator=( string_view_type source )
0139 {
0140 value_ = source;
0141 return *this;
0142 }
0143
0144 void swap( key_view& other ) noexcept
0145 {
0146 std::swap(value_, other.value_);
0147 }
0148
0149 string_view_type native() const noexcept {return value_;}
0150
0151 operator string_view_type() const {return native();}
0152
0153 int compare( const key_view& p ) const noexcept {return value_.compare(p.value_);}
0154 int compare( string_view_type str ) const {return value_.compare(str);}
0155 int compare( const value_type* s ) const {return value_.compare(s);}
0156
0157 template< class CharT, class Traits = std::char_traits<CharT>,
0158 class Alloc = std::allocator<CharT> >
0159 std::basic_string<CharT,Traits,Alloc>
0160 basic_string( const Alloc& alloc = Alloc()) const
0161 {
0162 return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
0163 value_.data(), value_.size(), alloc);
0164 }
0165
0166 std::string string() const {return basic_string<char>();}
0167 std::wstring wstring() const {return basic_string<wchar_t>();}
0168
0169 string_type native_string() const
0170 {
0171 return basic_string<char_type, key_char_traits<char_type>>();
0172 }
0173
0174 friend bool operator==(key_view l, key_view r) { return l.value_ == r.value_; }
0175 friend bool operator!=(key_view l, key_view r) { return l.value_ != r.value_; }
0176 friend bool operator<=(key_view l, key_view r) { return l.value_ <= r.value_; }
0177 friend bool operator>=(key_view l, key_view r) { return l.value_ >= r.value_; }
0178 friend bool operator< (key_view l, key_view r) { return l.value_ < r.value_; }
0179 friend bool operator> (key_view l, key_view r) { return l.value_ > r.value_; }
0180
0181 bool empty() const {return value_.empty(); }
0182
0183 template< class CharT, class Traits >
0184 friend std::basic_ostream<CharT,Traits>&
0185 operator<<( std::basic_ostream<CharT,Traits>& os, const key_view& p )
0186 {
0187 os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
0188 return os;
0189 }
0190
0191 template< class CharT, class Traits >
0192 friend std::basic_istream<CharT,Traits>&
0193 operator>>( std::basic_istream<CharT,Traits>& is, key_view& p )
0194 {
0195 std::basic_string<CharT, Traits> t;
0196 is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
0197 p = t;
0198 return is;
0199 }
0200 const value_type * data() const {return value_.data(); }
0201 std::size_t size() const {return value_.size(); }
0202 private:
0203 string_view_type value_;
0204 };
0205
0206
0207 struct value_view
0208 {
0209 using value_type = char_type;
0210 using string_view_type = basic_cstring_ref<char_type, value_char_traits<char_type>>;
0211 using string_type = std::basic_string<char_type, value_char_traits<char_type>>;
0212 using traits_type = value_char_traits<char_type>;
0213
0214 value_view() noexcept = default;
0215 value_view( const value_view& p ) = default;
0216 value_view( value_view&& p ) noexcept = default;
0217 template<typename Source, typename = typename std::enable_if<is_constructible<string_view_type, Source>::value>::type>
0218 value_view( const Source& source ) : value_(source) {}
0219 value_view( const char_type * p) : value_(p) {}
0220 value_view( char_type * p) : value_(p) {}
0221
0222 ~value_view() = default;
0223
0224 value_view& operator=( const value_view& p ) = default;
0225 value_view& operator=( value_view&& p ) noexcept = default;
0226 value_view& operator=( string_view_type source )
0227 {
0228 value_ = source;
0229 return *this;
0230 }
0231
0232 void swap( value_view& other ) noexcept
0233 {
0234 std::swap(value_, other.value_);
0235 }
0236
0237 string_view_type native() const noexcept {return value_;}
0238
0239 operator string_view_type() const {return native();}
0240 operator typename string_view_type::string_view_type() const {return value_; }
0241
0242 int compare( const value_view& p ) const noexcept {return value_.compare(p.value_);}
0243 int compare( string_view_type str ) const {return value_.compare(str);}
0244 int compare( const value_type* s ) const {return value_.compare(s);}
0245
0246 template< class CharT, class Traits = std::char_traits<CharT>,
0247 class Alloc = std::allocator<CharT> >
0248 std::basic_string<CharT,Traits,Alloc>
0249 basic_string( const Alloc& alloc = Alloc() ) const
0250 {
0251 return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
0252 value_.data(), value_.size(), alloc);
0253 }
0254
0255 std::string string() const {return basic_string<char>();}
0256 std::wstring wstring() const {return basic_string<wchar_t>();}
0257
0258 string_type native_string() const
0259 {
0260 return basic_string<char_type, value_char_traits<char_type>>();
0261 }
0262
0263 bool empty() const {return value_.empty(); }
0264
0265 friend bool operator==(value_view l, value_view r) { return l.value_ == r.value_; }
0266 friend bool operator!=(value_view l, value_view r) { return l.value_ != r.value_; }
0267 friend bool operator<=(value_view l, value_view r) { return l.value_ <= r.value_; }
0268 friend bool operator>=(value_view l, value_view r) { return l.value_ >= r.value_; }
0269 friend bool operator< (value_view l, value_view r) { return l.value_ < r.value_; }
0270 friend bool operator> (value_view l, value_view r) { return l.value_ > r.value_; }
0271
0272
0273 template< class CharT, class Traits >
0274 friend std::basic_ostream<CharT,Traits>&
0275 operator<<( std::basic_ostream<CharT,Traits>& os, const value_view& p )
0276 {
0277 os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
0278 return os;
0279 }
0280
0281 template< class CharT, class Traits >
0282 friend std::basic_istream<CharT,Traits>&
0283 operator>>( std::basic_istream<CharT,Traits>& is, value_view& p )
0284 {
0285 std::basic_string<CharT, Traits> t;
0286 is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
0287 p = t;
0288 return is;
0289 }
0290 value_iterator begin() const {return value_iterator(value_.data());}
0291 value_iterator end() const {return value_iterator(value_.data() , value_.size());}
0292
0293 const char_type * c_str() {return value_.c_str(); }
0294 const value_type * data() const {return value_.data(); }
0295 std::size_t size() const {return value_.size(); }
0296
0297 private:
0298 string_view_type value_;
0299 };
0300
0301
0302 struct key_value_pair_view
0303 {
0304 using value_type = char_type;
0305 using string_type = std::basic_string<char_type>;
0306 using string_view_type = basic_cstring_ref<char_type>;
0307 using traits_type = std::char_traits<char_type>;
0308
0309 key_value_pair_view() noexcept = default;
0310 key_value_pair_view( const key_value_pair_view& p ) = default;
0311 key_value_pair_view( key_value_pair_view&& p ) noexcept = default;
0312 template<typename Source,
0313 typename = typename std::enable_if<is_constructible<string_view_type, Source>::value>::type>
0314 key_value_pair_view( const Source& source ) : value_(source) {}
0315
0316 key_value_pair_view( const char_type * p) : value_(p) {}
0317 key_value_pair_view( char_type * p) : value_(p) {}
0318
0319
0320 ~key_value_pair_view() = default;
0321
0322 key_value_pair_view& operator=( const key_value_pair_view& p ) = default;
0323 key_value_pair_view& operator=( key_value_pair_view&& p ) noexcept = default;
0324
0325 void swap( key_value_pair_view& other ) noexcept
0326 {
0327 std::swap(value_, other.value_);
0328 }
0329
0330 string_view_type native() const noexcept {return value_;}
0331
0332 operator string_view_type() const {return native();}
0333 operator typename string_view_type::string_view_type() const {return value_; }
0334
0335 int compare( key_value_pair_view p ) const noexcept
0336 {
0337 const auto c = key().compare(p.key());
0338 if (c != 0)
0339 return c;
0340 return value().compare(p.value());
0341 }
0342 int compare( const string_type& str ) const
0343 {
0344 return compare(key_value_pair_view(str));
0345 }
0346 int compare( string_view_type str ) const
0347 {
0348 string_type st(str.data(), str.size());
0349 return compare(st);
0350 }
0351 int compare( const value_type* s ) const
0352 {
0353 return compare(key_value_pair_view(s));
0354 }
0355
0356 template< class CharT, class Traits = std::char_traits<CharT>, class Alloc = std::allocator<CharT> >
0357 std::basic_string<CharT,Traits,Alloc>
0358 basic_string( const Alloc& alloc = Alloc()) const
0359 {
0360 return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(value_.begin(), value_.size(), alloc);
0361 }
0362
0363 std::string string() const {return basic_string<char>();}
0364 std::wstring wstring() const {return basic_string<wchar_t>();}
0365
0366 string_type native_string() const
0367 {
0368 return basic_string<char_type>();
0369 }
0370
0371 bool empty() const {return value_.empty(); }
0372
0373 key_view key() const
0374 {
0375 auto eq = value_.find(equality_sign);
0376 if (eq == 0)
0377 {
0378 auto eq2 = value_.find(equality_sign, 1);
0379 if (eq2 != string_type::npos)
0380 eq = eq2;
0381 }
0382 const auto res = native().substr(0, eq == string_view_type::npos ? value_.size() : eq);
0383 return key_view::string_view_type(res.data(), res.size());
0384 }
0385 value_view value() const
0386 {
0387 auto eq = value_.find(equality_sign);
0388 if (eq == 0)
0389 {
0390 auto eq2 = value_.find(equality_sign, 1);
0391 if (eq2 != string_type::npos)
0392 eq = eq2;
0393 }
0394 return environment::value_view(native().substr(eq + 1));
0395 }
0396
0397 friend bool operator==(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) == 0; }
0398 friend bool operator!=(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) != 0; }
0399 friend bool operator<=(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) <= 0; }
0400 friend bool operator>=(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) >= 0; }
0401 friend bool operator< (key_value_pair_view l, key_value_pair_view r) { return l.compare(r) < 0; }
0402 friend bool operator> (key_value_pair_view l, key_value_pair_view r) { return l.compare(r) > 0; }
0403
0404
0405 template< class CharT, class Traits >
0406 friend std::basic_ostream<CharT,Traits>&
0407 operator<<( std::basic_ostream<CharT,Traits>& os, const key_value_pair_view& p )
0408 {
0409 os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
0410 return os;
0411 }
0412
0413 template< class CharT, class Traits >
0414 friend std::basic_istream<CharT,Traits>&
0415 operator>>( std::basic_istream<CharT,Traits>& is, key_value_pair_view& p )
0416 {
0417 std::basic_string<CharT, Traits> t;
0418 is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
0419 p = t;
0420 return is;
0421 }
0422
0423 template<std::size_t Idx>
0424 inline auto get() const -> typename conditional<Idx == 0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_view,
0425 BOOST_PROCESS_V2_NAMESPACE::environment::value_view>::type;
0426 const value_type * c_str() const noexcept
0427 {
0428 return value_.data();
0429 }
0430 const value_type * data() const {return value_.data(); }
0431 std::size_t size() const {return value_.size(); }
0432
0433 private:
0434
0435 string_view_type value_;
0436 };
0437
0438 template<>
0439 inline key_view key_value_pair_view::get<0u>() const
0440 {
0441 return key();
0442 }
0443
0444 template<>
0445 inline value_view key_value_pair_view::get<1u>() const
0446 {
0447 return value();
0448 }
0449
0450 namespace detail
0451 {
0452
0453 template<typename Char>
0454 std::size_t hash_step(std::size_t prev, Char c, std::char_traits<Char>)
0455 {
0456 return prev ^ (c << 1);
0457 }
0458
0459 }
0460
0461 inline std::size_t hash_value(const key_view & value)
0462 {
0463 std::size_t hash = 0u;
0464 for (auto c = value.data(); *c != *v2::detail::null_char_(*c); c++)
0465 hash = detail::hash_step(hash, *c, key_view::traits_type{});
0466 return hash ;
0467 }
0468
0469
0470 inline std::size_t hash_value(const BOOST_PROCESS_V2_NAMESPACE::environment::value_view & value)
0471 {
0472 std::size_t hash = 0u;
0473 for (auto c = value.data(); *c != *v2::detail::null_char_(*c); c++)
0474 hash = detail::hash_step(hash, *c, value_view::traits_type{});
0475 return hash ;
0476 }
0477
0478
0479 inline std::size_t hash_value(const BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view & value)
0480 {
0481 std::size_t hash = 0u;
0482 for (auto c = value.data(); *c != *v2::detail::null_char_(*c); c++)
0483 hash = detail::hash_step(hash, *c, key_value_pair_view::traits_type{});
0484 return hash ;
0485 }
0486
0487
0488 struct key
0489 {
0490 using value_type = char_type;
0491 using traits_type = key_char_traits<char_type>;
0492 using string_type = std::basic_string<char_type, traits_type>;
0493 using string_view_type = basic_string_view<char_type, traits_type>;
0494
0495 key() {}
0496 key( const key& p ) = default;
0497 key( key&& p ) noexcept = default;
0498 key( const string_type& source ) : value_(source) {}
0499 key( string_type&& source ) : value_(std::move(source)) {}
0500 key( const value_type * raw ) : value_(raw) {}
0501 key( value_type * raw ) : value_(raw) {}
0502
0503 explicit key(key_view kv) : value_(kv.native_string()) {}
0504
0505
0506 template< class Source >
0507 key( const Source& source,
0508 decltype(std::declval<Source>().data()) = nullptr,
0509 decltype(std::declval<Source>().size()) = 0u)
0510 : value_(
0511 BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0512 source.data(), source.size()))
0513 {
0514 }
0515
0516 key(const typename conditional<is_same<value_type, char>::value, wchar_t, char>::type * raw)
0517 : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0518 raw, std::char_traits<std::decay<std::remove_pointer<decltype(raw)>::type>::type>::length(raw)))
0519 {
0520 }
0521
0522 template< class InputIt >
0523 key( InputIt first, InputIt last)
0524 : key(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last))
0525 {
0526 }
0527
0528 ~key() = default;
0529
0530 key& operator=( const key& p ) = default;
0531 key& operator=( key&& p )
0532 {
0533 value_ = std::move(p.value_);
0534 return *this;
0535 }
0536 key& operator=( string_type&& source )
0537 {
0538 value_ = std::move(source);
0539 return *this;
0540 }
0541 template< class Source >
0542 key& operator=( const Source& source )
0543 {
0544 value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(source.data(), source.size());
0545 return *this;
0546 }
0547
0548 key& assign( string_type&& source )
0549 {
0550 value_ = std::move(source);
0551 return *this;
0552 }
0553 template< class Source >
0554 key& assign( const Source& source )
0555 {
0556 value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(source.data(), source.size());
0557 return *this;
0558 }
0559
0560 template< class InputIt >
0561 key& assign( InputIt first, InputIt last )
0562 {
0563
0564 return assign(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last));
0565 }
0566
0567 void clear() {value_.clear();}
0568
0569 void swap( key& other ) noexcept
0570 {
0571 std::swap(value_, other.value_);
0572 }
0573
0574 const value_type* c_str() const noexcept {return value_.c_str();}
0575 const string_type& native() const noexcept {return value_;}
0576 string_view_type native_view() const noexcept {return value_;}
0577
0578 operator string_type() const {return native();}
0579 operator string_view_type() const {return native_view();}
0580
0581 int compare( const key& p ) const noexcept {return value_.compare(p.value_);}
0582 int compare( const string_type& str ) const {return value_.compare(str);}
0583 int compare( string_view_type str ) const {return -str.compare(value_);}
0584 int compare( const value_type* s ) const {return value_.compare(s);}
0585
0586 template< class CharT, class Traits = std::char_traits<CharT>,
0587 class Alloc = std::allocator<CharT> >
0588 std::basic_string<CharT,Traits,Alloc>
0589 basic_string( const Alloc& alloc = Alloc()) const
0590 {
0591 return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
0592 value_.data(), value_.size(), alloc);
0593 }
0594
0595
0596 std::string string() const {return basic_string<char>();}
0597 std::wstring wstring() const {return basic_string<wchar_t>();}
0598
0599 const string_type & native_string() const
0600 {
0601 return value_;
0602 }
0603
0604 bool empty() const {return value_.empty(); }
0605
0606 friend bool operator==(const key & l, const key & r) { return l.value_ == r.value_; }
0607 friend bool operator!=(const key & l, const key & r) { return l.value_ != r.value_; }
0608 friend bool operator<=(const key & l, const key & r) { return l.value_ <= r.value_; }
0609 friend bool operator>=(const key & l, const key & r) { return l.value_ >= r.value_; }
0610 friend bool operator< (const key & l, const key & r) { return l.value_ < r.value_; }
0611 friend bool operator> (const key & l, const key & r) { return l.value_ > r.value_; }
0612
0613 template< class CharT, class Traits >
0614 friend std::basic_ostream<CharT,Traits>&
0615 operator<<( std::basic_ostream<CharT,Traits>& os, const key& p )
0616 {
0617 os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
0618 return os;
0619 }
0620
0621 template< class CharT, class Traits >
0622 friend std::basic_istream<CharT,Traits>&
0623 operator>>( std::basic_istream<CharT,Traits>& is, key& p )
0624 {
0625 std::basic_string<CharT, Traits> t;
0626 is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
0627 p = t;
0628 return is;
0629 }
0630 const value_type * data() const {return value_.data(); }
0631 std::size_t size() const {return value_.size(); }
0632
0633 private:
0634 string_type value_;
0635 };
0636
0637 #if !defined(GENERATING_DOCUMENTATION)
0638
0639 template<typename T, typename U>
0640 typename std::enable_if<
0641 ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
0642 std::is_convertible<const U &, key_view>::value)
0643 ||
0644 ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
0645 std::is_convertible<const T & , key_view>::value),
0646 bool>::type
0647 operator==(const T &l, const U & r) { return key_view(l) == key_view(r); }
0648
0649 template<typename T, typename U>
0650 typename std::enable_if<
0651 ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
0652 std::is_convertible<const U &, key_view>::value)
0653 ||
0654 ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
0655 std::is_convertible<const T & , key_view>::value),
0656 bool>::type
0657 operator!=(const T &l, const U & r) { return key_view(l) != key_view(r); }
0658
0659 template<typename T, typename U>
0660 typename std::enable_if<
0661 ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
0662 std::is_convertible<const U &, key_view>::value)
0663 ||
0664 ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
0665 std::is_convertible<const T & , key_view>::value),
0666 bool>::type
0667 operator<=(const T &l, const U & r) { return key_view(l) <= key_view(r); }
0668
0669 template<typename T, typename U>
0670 typename std::enable_if<
0671 ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
0672 std::is_convertible<const U &, key_view>::value)
0673 ||
0674 ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
0675 std::is_convertible<const T & , key_view>::value),
0676 bool>::type
0677 operator <(const T &l, const U & r) { return key_view(l) < key_view(r); }
0678
0679 template<typename T, typename U>
0680 typename std::enable_if<
0681 ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
0682 std::is_convertible<const U &, key_view>::value)
0683 ||
0684 ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
0685 std::is_convertible<const T & , key_view>::value),
0686 bool>::type
0687 operator>=(const T &l, const U & r) { return key_view(l) >= key_view(r); }
0688
0689 template<typename T, typename U>
0690 typename std::enable_if<
0691 ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
0692 std::is_convertible<const U &, key_view>::value)
0693 ||
0694 ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
0695 std::is_convertible<const T & , key_view>::value),
0696 bool>::type
0697 operator >(const T &l, const U & r) { return key_view(l) > key_view(r); }
0698
0699 #else
0700
0701
0702 bool operator==(const value_view &, const value_view);
0703 bool operator!=(const value_view &, const value_view);
0704 bool operator<=(const value_view &, const value_view);
0705 bool operator< (const value_view &, const value_view);
0706 bool operator> (const value_view &, const value_view);
0707 bool operator>=(const value_view &, const value_view);
0708
0709 #endif
0710
0711
0712 struct value
0713 {
0714 using value_type = char_type;
0715 using traits_type = value_char_traits<char_type>;
0716 using string_type = std::basic_string<char_type, traits_type>;
0717 using string_view_type = basic_cstring_ref<char_type, traits_type>;
0718
0719 value() {}
0720 value( const value& p ) = default;
0721
0722 value( const string_type& source ) : value_(source) {}
0723 value( string_type&& source ) : value_(std::move(source)) {}
0724 value( const value_type * raw ) : value_(raw) {}
0725 value( value_type * raw ) : value_(raw) {}
0726
0727 explicit value(value_view kv) : value_(kv.c_str()) {}
0728
0729 template< class Source >
0730 value( const Source& source,
0731 decltype(std::declval<Source>().data()) = nullptr,
0732 decltype(std::declval<Source>().size()) = 0u)
0733 : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0734 source.data(), source.size()))
0735 {
0736 }
0737
0738 value(const typename conditional<is_same<value_type, char>::value, wchar_t, char>::type * raw)
0739 : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0740 raw, std::char_traits<std::decay<std::remove_pointer<decltype(raw)>::type>::type>::length(raw)))
0741 {
0742 }
0743
0744 template< class InputIt >
0745 value( InputIt first, InputIt last)
0746 : value(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last))
0747 {
0748 }
0749
0750 ~value() = default;
0751
0752 value& operator=( const value& p ) = default;
0753 value& operator=( value&& p )
0754 {
0755 value_ = std::move(p.value_);
0756 return *this;
0757 }
0758 value& operator=( string_type&& source )
0759 {
0760 value_ = std::move(source);
0761 return *this;
0762 }
0763 template< class Source >
0764 value& operator=( const Source& source )
0765 {
0766 value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0767 source.data(), source.size);
0768 return *this;
0769 }
0770
0771 value& assign( string_type&& source )
0772 {
0773 value_ = std::move(source);
0774 return *this;
0775 }
0776 template< class Source >
0777 value& assign( const Source& source )
0778 {
0779 value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0780 source.data(), source.size());
0781 return *this;
0782 }
0783
0784 template< class InputIt >
0785 value& assign( InputIt first, InputIt last )
0786 {
0787 return assign(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last));
0788 }
0789
0790 void push_back(const value & sv)
0791 {
0792 (value_ += delimiter) += sv;
0793 }
0794
0795 void clear() {value_.clear();}
0796
0797 void swap( value& other ) noexcept
0798 {
0799 std::swap(value_, other.value_);
0800 }
0801
0802 const value_type* c_str() const noexcept {return value_.c_str();}
0803 const string_type& native() const noexcept {return value_;}
0804 string_view_type native_view() const noexcept {return value_;}
0805
0806 operator string_type() const {return native();}
0807 operator string_view_type() const {return native_view();}
0808 operator typename string_view_type::string_view_type() const {return value_; }
0809
0810 int compare( const value& p ) const noexcept {return value_.compare(p.value_);}
0811 int compare( const string_type& str ) const {return value_.compare(str);}
0812 int compare( string_view_type str ) const {return -str.compare(value_);}
0813 int compare( const value_type* s ) const {return value_.compare(s);}
0814
0815 template< class CharT, class Traits = std::char_traits<CharT>,
0816 class Alloc = std::allocator<CharT> >
0817 std::basic_string<CharT,Traits,Alloc>
0818 basic_string( const Alloc& alloc = Alloc()) const
0819 {
0820 return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
0821 value_.data(), value_.size(),alloc);
0822 }
0823
0824 std::string string() const {return basic_string<char>();}
0825 std::wstring wstring() const {return basic_string<wchar_t>();}
0826
0827
0828 const string_type & native_string() const
0829 {
0830 return value_;
0831 }
0832
0833 bool empty() const {return value_.empty(); }
0834
0835 friend bool operator==(const value & l, const value & r) { return l.value_ == r.value_; }
0836 friend bool operator!=(const value & l, const value & r) { return l.value_ != r.value_; }
0837 friend bool operator<=(const value & l, const value & r) { return l.value_ <= r.value_; }
0838 friend bool operator>=(const value & l, const value & r) { return l.value_ >= r.value_; }
0839 friend bool operator< (const value & l, const value & r) { return l.value_ < r.value_; }
0840 friend bool operator> (const value & l, const value & r) { return l.value_ > r.value_; }
0841
0842 template< class CharT, class Traits >
0843 friend std::basic_ostream<CharT,Traits>&
0844 operator<<( std::basic_ostream<CharT,Traits>& os, const value& p )
0845 {
0846 os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
0847 return os;
0848 }
0849
0850 template< class CharT, class Traits >
0851 friend std::basic_istream<CharT,Traits>&
0852 operator>>( std::basic_istream<CharT,Traits>& is, value& p )
0853 {
0854 std::basic_string<CharT, Traits> t;
0855 is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
0856 p = t;
0857 return is;
0858 }
0859
0860 value_iterator begin() const {return value_iterator(value_.data());}
0861 value_iterator end() const {return value_iterator(value_.data(), value_.size());}
0862 const value_type * data() const {return value_.data(); }
0863 std::size_t size() const {return value_.size(); }
0864
0865 private:
0866 string_type value_;
0867 };
0868
0869
0870 #if !defined(GENERATING_DOCUMENTATION)
0871
0872 template<typename T, typename U>
0873 typename std::enable_if<
0874 ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
0875 std::is_convertible<const U &, value_view>::value)
0876 ||
0877 ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
0878 std::is_convertible<const T & , value_view>::value),
0879 bool>::type
0880 operator==(const T &l, const U & r) { return value_view(l) == value_view(r); }
0881
0882 template<typename T, typename U>
0883 typename std::enable_if<
0884 ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
0885 std::is_convertible<const U &, value_view>::value)
0886 ||
0887 ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
0888 std::is_convertible<const T & , value_view>::value),
0889 bool>::type
0890 operator!=(const T &l, const U & r) { return value_view(l) != value_view(r); }
0891
0892 template<typename T, typename U>
0893 typename std::enable_if<
0894 ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
0895 std::is_convertible<const U &, value_view>::value)
0896 ||
0897 ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
0898 std::is_convertible<const T & , value_view>::value),
0899 bool>::type
0900 operator<=(const T &l, const U & r) { return value_view(l) <= value_view(r); }
0901
0902 template<typename T, typename U>
0903 typename std::enable_if<
0904 ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
0905 std::is_convertible<const U &, value_view>::value)
0906 ||
0907 ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
0908 std::is_convertible<const T & , value_view>::value),
0909 bool>::type
0910 operator <(const T &l, const U & r) { return value_view(l) < value_view(r); }
0911
0912 template<typename T, typename U>
0913 typename std::enable_if<
0914 ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
0915 std::is_convertible<const U &, value_view>::value)
0916 ||
0917 ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
0918 std::is_convertible<const T & , value_view>::value),
0919 bool>::type
0920 operator>=(const T &l, const U & r) { return value_view(l) >= value_view(r); }
0921
0922 template<typename T, typename U>
0923 typename std::enable_if<
0924 ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
0925 std::is_convertible<const U &, value_view>::value)
0926 ||
0927 ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
0928 std::is_convertible<const T & , value_view>::value),
0929 bool>::type
0930 operator >(const T &l, const U & r) { return value_view(l) > value_view(r); }
0931
0932 #else
0933
0934 bool operator==(const value_view &, const value_view);
0935 bool operator!=(const value_view &, const value_view);
0936 bool operator<=(const value_view &, const value_view);
0937 bool operator< (const value_view &, const value_view);
0938 bool operator> (const value_view &, const value_view);
0939 bool operator>=(const value_view &, const value_view);
0940
0941 #endif
0942
0943 struct key_value_pair
0944 {
0945 using value_type = char_type;
0946 using traits_type = std::char_traits<char_type>;
0947 using string_type = std::basic_string<char_type>;
0948 using string_view_type = basic_cstring_ref<char_type>;
0949
0950 key_value_pair() {}
0951 key_value_pair( const key_value_pair& p ) = default;
0952 key_value_pair( key_value_pair&& p ) noexcept = default;
0953 key_value_pair(key_view key, value_view value) : value_(key.basic_string<char_type, traits_type>() + equality_sign +
0954 value.basic_string<char_type, traits_type>()) {}
0955
0956 key_value_pair(key_view key, std::initializer_list<basic_string_view<char_type>> values)
0957 {
0958 const auto sz = std::accumulate(values.begin(), values.end(),
0959 key.size(), [](std::size_t sz, const basic_string_view<char_type> & str) { return sz + str.size() + 1;});
0960
0961 value_.reserve(sz);
0962 value_.append(key.data(), key.size());
0963 value_ += equality_sign;
0964 for (auto & value : values)
0965 {
0966 if (value_.back() != equality_sign)
0967 value_ += delimiter;
0968 value_.append(value.data(), value.size());
0969 }
0970 }
0971
0972 key_value_pair( const string_type& source ) : value_(source) {}
0973 key_value_pair( string_type&& source ) : value_(std::move(source)) {}
0974 key_value_pair( const value_type * raw ) : value_(raw) {}
0975 key_value_pair( value_type * raw ) : value_(raw) {}
0976
0977 explicit key_value_pair(key_value_pair_view kv) : value_(kv.c_str()) {}
0978
0979 template< class Source >
0980 key_value_pair( const Source& source,
0981 decltype(std::declval<Source>().data()) = nullptr,
0982 decltype(std::declval<Source>().size()) = 0u)
0983 : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
0984 source.data(), source.size()))
0985 {
0986 }
0987
0988 template< typename Key,
0989 typename Value >
0990 key_value_pair(
0991 const std::pair<Key, Value> & kv
0992
0993
0994 ) : value_(((struct key)(kv.first)).basic_string<char_type, traits_type>() + equality_sign
0995 + ((struct value)(kv.second)).basic_string<char_type, traits_type>())
0996 {}
0997
0998 key_value_pair(const typename conditional<is_same<value_type, char>::value, wchar_t, char>::type * raw)
0999 : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
1000 raw,
1001 std::char_traits<std::decay<std::remove_pointer<decltype(raw)>::type>::type>::length(raw)))
1002 {
1003 }
1004
1005 template< class InputIt , typename std::iterator_traits<InputIt>::iterator_category>
1006 key_value_pair( InputIt first, InputIt last )
1007 : key_value_pair(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last))
1008 {
1009 }
1010
1011 ~key_value_pair() = default;
1012
1013 key_value_pair& operator=( const key_value_pair& p ) = default;
1014 key_value_pair& operator=( key_value_pair&& p )
1015 {
1016 value_ = std::move(p.value_);
1017 return *this;
1018 }
1019 key_value_pair& operator=( string_type&& source )
1020 {
1021 value_ = std::move(source);
1022 return *this;
1023 }
1024 template< class Source >
1025 key_value_pair& operator=( const Source& source )
1026 {
1027 value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
1028 source.data(), source.size());
1029 return *this;
1030 }
1031
1032 key_value_pair& assign( string_type&& source )
1033 {
1034 value_ = std::move(source);
1035 return *this;
1036 }
1037 template< class Source >
1038 key_value_pair& assign( const Source& source )
1039 {
1040 value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
1041 source.data(), source.size());
1042 return *this;
1043 }
1044
1045
1046 template< class InputIt >
1047 key_value_pair& assign( InputIt first, InputIt last )
1048 {
1049 return assign(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last));
1050 }
1051
1052 void clear() {value_.clear();}
1053
1054 void swap( key_value_pair& other ) noexcept
1055 {
1056 std::swap(value_, other.value_);
1057 }
1058
1059 const value_type* c_str() const noexcept {return value_.c_str();}
1060 const string_type& native() const noexcept {return value_;}
1061 string_view_type native_view() const noexcept {return value_;}
1062
1063 operator string_type() const {return native();}
1064 operator string_view_type() const {return native_view();}
1065 operator typename string_view_type::string_view_type() const {return native_view();}
1066 operator key_value_pair_view() const {return native_view();}
1067
1068 int compare( const key_value_pair& p ) const noexcept
1069 {
1070 return key_value_pair_view(*this).compare(key_value_pair_view(p));
1071 }
1072
1073 int compare( const string_type& str ) const
1074 {
1075 return key_value_pair_view(*this).compare(str);
1076 }
1077 int compare( string_view_type str ) const
1078 {
1079 return key_value_pair_view(*this).compare(str);
1080 }
1081 int compare( const value_type* s ) const
1082 {
1083 return key_value_pair_view(*this).compare(s);
1084 }
1085
1086 template< class CharT, class Traits = std::char_traits<CharT>, class Alloc = std::allocator<CharT> >
1087 std::basic_string<CharT,Traits,Alloc>
1088 basic_string( const Alloc& alloc = Alloc() ) const
1089 {
1090 return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(value_.data(), value_.size(), alloc);
1091 }
1092
1093 std::string string() const {return basic_string<char>();}
1094 std::wstring wstring() const {return basic_string<wchar_t>();}
1095
1096 const string_type & native_string() const
1097 {
1098 return value_;
1099 }
1100
1101 friend bool operator==(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) == 0; }
1102 friend bool operator!=(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) != 0; }
1103 friend bool operator<=(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) <= 0; }
1104 friend bool operator>=(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) >= 0; }
1105 friend bool operator< (const key_value_pair & l, const key_value_pair & r) { return l.compare(r) < 0; }
1106 friend bool operator> (const key_value_pair & l, const key_value_pair & r) { return l.compare(r) > 0; }
1107
1108 bool empty() const {return value_.empty(); }
1109
1110 struct key_view key() const
1111 {
1112 auto eq = value_.find(equality_sign);
1113 if (eq == 0)
1114 {
1115 auto eq2 = value_.find(equality_sign, 1);
1116 if (eq2 != string_type::npos)
1117 eq = eq2;
1118 }
1119 const auto k = native_view().substr(0, eq);
1120
1121 return BOOST_PROCESS_V2_NAMESPACE::environment::key_view::string_view_type (k.data(), k.size());
1122 }
1123 struct value_view value() const
1124 {
1125 auto eq = value_.find(equality_sign);
1126 if (eq == 0)
1127 {
1128 auto eq2 = value_.find(equality_sign, 1);
1129 if (eq2 != string_type::npos)
1130 eq = eq2;
1131 }
1132 return value_view::string_view_type(native_view().substr(eq + 1));
1133 }
1134
1135 template< class CharT, class Traits >
1136 friend std::basic_ostream<CharT,Traits>&
1137 operator<<( std::basic_ostream<CharT,Traits>& os, const key_value_pair& p )
1138 {
1139 os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
1140 return os;
1141 }
1142
1143 template< class CharT, class Traits >
1144 friend std::basic_istream<CharT,Traits>&
1145 operator>>( std::basic_istream<CharT,Traits>& is, key_value_pair& p )
1146 {
1147 is >> BOOST_PROCESS_V2_NAMESPACE::quoted(p.value_);
1148 return is;
1149 }
1150
1151 const value_type * data() const {return value_.data(); }
1152 std::size_t size() const {return value_.size(); }
1153
1154 template<std::size_t Idx>
1155 inline auto get() const
1156 -> typename conditional<Idx == 0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_view,
1157 BOOST_PROCESS_V2_NAMESPACE::environment::value_view>::type;
1158
1159 private:
1160 string_type value_;
1161 };
1162
1163 #if !defined(GENERATING_DOCUMENTATION)
1164
1165 template<typename T, typename U>
1166 typename std::enable_if<
1167 ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
1168 std::is_convertible<const U &, key_value_pair_view>::value)
1169 ||
1170 ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
1171 std::is_convertible<const T & , key_value_pair_view>::value),
1172 bool>::type
1173 operator==(const T &l, const U & r) { return key_value_pair_view(l) == key_value_pair_view(r); }
1174
1175 template<typename T, typename U>
1176 typename std::enable_if<
1177 ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
1178 std::is_convertible<const U &, key_value_pair_view>::value)
1179 ||
1180 ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
1181 std::is_convertible<const T & , key_value_pair_view>::value),
1182 bool>::type
1183 operator!=(const T &l, const U & r) { return key_value_pair_view(l) != key_value_pair_view(r); }
1184
1185 template<typename T, typename U>
1186 typename std::enable_if<
1187 ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
1188 std::is_convertible<const U &, key_value_pair_view>::value)
1189 ||
1190 ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
1191 std::is_convertible<const T & , key_value_pair_view>::value),
1192 bool>::type
1193 operator<=(const T &l, const U & r) { return key_value_pair_view(l) <= key_value_pair_view(r); }
1194
1195 template<typename T, typename U>
1196 typename std::enable_if<
1197 ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
1198 std::is_convertible<const U &, key_value_pair_view>::value)
1199 ||
1200 ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
1201 std::is_convertible<const T & , key_value_pair_view>::value),
1202 bool>::type
1203 operator <(const T &l, const U & r) { return key_value_pair_view(l) < key_value_pair_view(r); }
1204
1205 template<typename T, typename U>
1206 typename std::enable_if<
1207 ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
1208 std::is_convertible<const U &, key_value_pair_view>::value)
1209 ||
1210 ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
1211 std::is_convertible<const T & , key_value_pair_view>::value),
1212 bool>::type
1213 operator>=(const T &l, const U & r) { return key_value_pair_view(l) >= key_value_pair_view(r); }
1214
1215 template<typename T, typename U>
1216 typename std::enable_if<
1217 ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
1218 std::is_convertible<const U &, key_value_pair_view>::value)
1219 ||
1220 ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
1221 std::is_convertible<const T & , key_value_pair_view>::value),
1222 bool>::type
1223 operator >(const T &l, const U & r) { return key_value_pair_view(l) > key_value_pair_view(r); }
1224
1225 #else
1226
1227 bool operator==(const key_value_pair_view &, const key_value_pair_view);
1228 bool operator!=(const key_value_pair_view &, const key_value_pair_view);
1229 bool operator<=(const key_value_pair_view &, const key_value_pair_view);
1230 bool operator< (const key_value_pair_view &, const key_value_pair_view);
1231 bool operator> (const key_value_pair_view &, const key_value_pair_view);
1232 bool operator>=(const key_value_pair_view &, const key_value_pair_view);
1233
1234 #endif
1235
1236
1237 template<>
1238 inline key_view key_value_pair::get<0u>() const
1239 {
1240 return key();
1241 }
1242
1243 template<>
1244 inline value_view key_value_pair::get<1u>() const
1245 {
1246 return value();
1247 }
1248
1249 }
1250 BOOST_PROCESS_V2_END_NAMESPACE
1251
1252 namespace std
1253 {
1254
1255 template<>
1256 class tuple_size<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair> : integral_constant<std::size_t, 2u> {};
1257
1258 template<>
1259 class tuple_element<0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
1260 {
1261 public:
1262 using type = BOOST_PROCESS_V2_NAMESPACE::environment::key_view;
1263 };
1264
1265 template<>
1266 class tuple_element<1u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
1267 {
1268 public:
1269 using type = BOOST_PROCESS_V2_NAMESPACE::environment::value_view;
1270 };
1271
1272 template<std::size_t Idx>
1273 inline auto get(const BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair & kvp)
1274 -> typename std::tuple_element<Idx, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>::type
1275 {
1276 return kvp.get<Idx>();
1277 }
1278
1279 template<>
1280 class tuple_size<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view> : integral_constant<std::size_t, 2u> {};
1281
1282 template<>
1283 class tuple_element<0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>
1284 {
1285 public:
1286 using type = BOOST_PROCESS_V2_NAMESPACE::environment::key_view;
1287 };
1288
1289 template<>
1290 class tuple_element<1u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>
1291 {
1292 public:
1293 using type = BOOST_PROCESS_V2_NAMESPACE::environment::value_view;
1294 };
1295
1296 template<std::size_t Idx>
1297 inline auto get(BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view kvp)
1298 -> typename std::tuple_element<Idx, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>::type
1299 {
1300 return kvp.get<Idx>();
1301 }
1302
1303 }
1304
1305 BOOST_PROCESS_V2_BEGIN_NAMESPACE
1306 namespace environment
1307 {
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329 struct current_view
1330 {
1331 using native_handle_type = environment::native_handle_type;
1332 using value_type = key_value_pair_view;
1333
1334 current_view() = default;
1335 current_view(current_view && nt) = default;
1336
1337 native_handle_type native_handle() { return handle_.get(); }
1338
1339 struct iterator
1340 {
1341 using value_type = key_value_pair_view;
1342 using difference_type = int;
1343 using reference = key_value_pair_view;
1344 using pointer = key_value_pair_view;
1345 using iterator_category = std::forward_iterator_tag;
1346
1347 iterator() = default;
1348 iterator(const iterator & ) = default;
1349 iterator(const native_iterator &native_handle) : iterator_(native_handle) {}
1350
1351 iterator & operator++()
1352 {
1353 iterator_ = detail::next(iterator_);
1354 return *this;
1355 }
1356
1357 iterator operator++(int)
1358 {
1359 auto last = *this;
1360 iterator_ = detail::next(iterator_);
1361 return last;
1362 }
1363 key_value_pair_view operator*() const
1364 {
1365 return detail::dereference(iterator_);
1366 }
1367
1368 friend bool operator==(const iterator & l, const iterator & r) {return l.iterator_ == r.iterator_;}
1369 friend bool operator!=(const iterator & l, const iterator & r) {return l.iterator_ != r.iterator_;}
1370
1371 private:
1372 environment::native_iterator iterator_;
1373 };
1374
1375 iterator begin() const {return iterator(handle_.get());}
1376 iterator end() const {return iterator(detail::find_end(handle_.get()));}
1377
1378 private:
1379
1380 std::unique_ptr<typename remove_pointer<native_handle_type>::type,
1381 detail::native_handle_deleter> handle_{environment::detail::load_native_handle()};
1382 };
1383
1384
1385 inline current_view current() {return current_view();}
1386
1387 namespace detail
1388 {
1389
1390 template<typename Environment>
1391 auto find_key(Environment & env, key_view ky)
1392 -> typename std::enable_if<std::is_convertible<decltype(*std::begin(env)), key_value_pair_view>::value, value_view>::type
1393 {
1394 const auto itr = std::find_if(std::begin(env), std::end(env),
1395 [&](key_value_pair_view vp)
1396 {
1397 auto tmp = std::get<0>(vp) == ky;
1398 if (tmp)
1399 return true;
1400 else
1401 return false;
1402 });
1403
1404 if (itr != std::end(env))
1405 return key_value_pair_view(*itr).value();
1406 else
1407 return {};
1408 }
1409
1410 template<typename Environment>
1411 auto find_key(Environment & env, key_view ky)
1412 -> typename std::enable_if<
1413 !std::is_convertible<decltype(*std::begin(env)), key_value_pair_view>::value &&
1414 std::is_convertible<decltype(*std::begin(env)), key_value_pair>::value,
1415 value>::type
1416 {
1417 const auto itr = std::find_if(std::begin(env), std::end(env),
1418 [&](key_value_pair vp)
1419 {
1420 auto tmp = std::get<0>(vp) == ky;
1421 if (tmp)
1422 return true;
1423 else
1424 return false;
1425 });
1426 if (itr != std::end(env))
1427 return key_value_pair(*itr).value();
1428 else
1429 return {};
1430 }
1431
1432
1433 }
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450 template<typename Environment = current_view>
1451 inline filesystem::path home(Environment && env = current())
1452 {
1453 #if defined(BOOST_PROCESS_V2_WINDOWS)
1454 return detail::find_key(env, L"HOMEDRIVE").native_string()
1455 + detail::find_key(env, L"HOMEPATH").native_string();
1456 #else
1457 return detail::find_key(env, "HOME").native_string();
1458 #endif
1459 }
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476 template<typename Environment = current_view>
1477 inline BOOST_PROCESS_V2_NAMESPACE::filesystem::path find_executable(
1478 BOOST_PROCESS_V2_NAMESPACE::filesystem::path name,
1479 Environment && env = current())
1480 {
1481
1482 #if defined(BOOST_PROCESS_V2_WINDOWS)
1483 auto path = detail::find_key(env, L"PATH");
1484 auto pathext = detail::find_key(env, L"PATHEXT");
1485 for (auto pp_view : path)
1486 {
1487
1488 BOOST_PROCESS_V2_NAMESPACE::filesystem::path full_nm(name);
1489 BOOST_PROCESS_V2_NAMESPACE::filesystem::path pp(pp_view.begin(), pp_view.end());
1490 auto p = pp / full_nm;
1491 error_code ec;
1492
1493 if (detail::is_executable(p, ec) && !ec)
1494 return p;
1495
1496 for (auto ext : pathext)
1497 {
1498 ec.clear();
1499 BOOST_PROCESS_V2_NAMESPACE::filesystem::path nm(name);
1500 nm.concat(ext.begin(), ext.end());
1501
1502 auto p = pp / nm;
1503
1504 if (detail::is_executable(p, ec) && !ec)
1505 return p;
1506 }
1507 }
1508 #else
1509 for (auto pp_view : detail::find_key(env, "PATH"))
1510 {
1511 auto p = BOOST_PROCESS_V2_NAMESPACE::filesystem::path(pp_view.begin(), pp_view.end()) / name;
1512 error_code ec;
1513 bool is_exec = detail::is_executable(p, ec);
1514 if (!ec && is_exec)
1515 return p;
1516 }
1517 #endif
1518 return {};
1519 }
1520
1521
1522 inline value get(const key & k, error_code & ec) { return detail::get(k.c_str(), ec);}
1523
1524 inline value get(const key & k)
1525 {
1526 error_code ec;
1527 auto tmp = detail::get(k.c_str(), ec);
1528 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::get");
1529 return tmp;
1530 }
1531
1532
1533 inline value get(basic_cstring_ref<char_type, key_char_traits<char_type>> k, error_code & ec)
1534 {
1535 return detail::get(k, ec);
1536 }
1537
1538 inline value get(basic_cstring_ref<char_type, key_char_traits<char_type>> k)
1539 {
1540 error_code ec;
1541 auto tmp = detail::get(k, ec);
1542 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::get");
1543 return tmp;
1544 }
1545
1546
1547
1548 inline value get(const char_type * c, error_code & ec) { return detail::get(c, ec);}
1549
1550 inline value get(const char_type * c)
1551 {
1552 error_code ec;
1553 auto tmp = detail::get(c, ec);
1554 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::get");
1555 return tmp;
1556 }
1557
1558
1559 inline void set(const key & k, value_view vw, error_code & ec) { detail::set(k, vw, ec);}
1560
1561 inline void set(const key & k, value_view vw)
1562 {
1563 error_code ec;
1564 detail::set(k, vw, ec);
1565 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
1566 }
1567
1568
1569 inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, value_view vw, error_code & ec) { detail::set(k, vw, ec);}
1570
1571 inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, value_view vw)
1572 {
1573 error_code ec;
1574 detail::set(k, vw, ec);
1575 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
1576 }
1577
1578
1579
1580 inline void set(const char_type * k, value_view vw, error_code & ec) { detail::set(k, vw, ec);}
1581
1582 inline void set(const char_type * k, value_view vw)
1583 {
1584 error_code ec;
1585 detail::set(k, vw, ec);
1586 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
1587 }
1588
1589
1590 template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
1591 inline void set(const key & k, const Char * vw, error_code & ec)
1592 {
1593 value val{vw};
1594 detail::set(k, val, ec);
1595 }
1596
1597 template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
1598 inline void set(const key & k, const Char * vw)
1599 {
1600 error_code ec;
1601 value val{vw};
1602 detail::set(k, val, ec);
1603 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
1604 }
1605
1606
1607 template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
1608 inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, const Char * vw, error_code & ec)
1609 {
1610 value val{vw};
1611 detail::set(k, val, ec);
1612 }
1613
1614
1615 template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
1616 inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, const Char * vw)
1617 {
1618 error_code ec;
1619 value val{vw};
1620 detail::set(k, val, ec);
1621 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
1622 }
1623
1624
1625 template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
1626 inline void set(const char_type * k, const Char * vw, error_code & ec)
1627 {
1628 value val{vw};
1629 detail::set(k, val, ec);
1630 }
1631
1632
1633 template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
1634 inline void set(const char_type * k, const Char * vw)
1635 {
1636 error_code ec;
1637 value val{vw};
1638 detail::set(k, val, ec);
1639 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
1640 }
1641
1642
1643
1644 inline void unset(const key & k, error_code & ec) { detail::unset(k, ec);}
1645
1646 inline void unset(const key & k)
1647 {
1648 error_code ec;
1649 detail::unset(k, ec);
1650 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::unset");
1651 }
1652
1653
1654 inline void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> k, error_code & ec)
1655 {
1656 detail::unset(k, ec);
1657 }
1658
1659
1660 inline void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> k)
1661 {
1662 error_code ec;
1663 detail::unset(k, ec);
1664 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::unset");
1665 }
1666
1667
1668 inline void unset(const char_type * c, error_code & ec) { detail::unset(c, ec);}
1669
1670
1671 inline void unset(const char_type * c)
1672 {
1673 error_code ec;
1674 detail::unset(c, ec);
1675 BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::unset");
1676 }
1677 }
1678
1679
1680
1681 #if defined(BOOST_PROCESS_V2_WINDOWS)
1682 namespace windows { struct default_launcher ;}
1683 #else
1684 namespace posix { struct default_launcher ;}
1685 #endif
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710 struct process_environment
1711 {
1712
1713 #if defined(BOOST_PROCESS_V2_WINDOWS)
1714
1715
1716 template<typename Args>
1717 static
1718 std::vector<wchar_t> build_env(Args && args,
1719 typename std::enable_if<
1720 std::is_convertible<
1721 decltype(*std::begin(std::declval<Args>())),
1722 wcstring_ref>::value>::type * = nullptr)
1723 {
1724 std::vector<wchar_t> res;
1725 std::size_t sz = 1;
1726 for (wcstring_ref cs : std::forward<Args>(args))
1727 sz =+ cs.size() + 1;
1728 res.reserve(sz);
1729
1730 for (wcstring_ref cs : std::forward<Args>(args))
1731 res.insert(res.end(), cs.begin(), std::next(cs.end()));
1732
1733
1734 res.push_back(L'\0');
1735 return res;
1736 }
1737
1738 template<typename Args>
1739 std::vector<wchar_t> build_env(Args && args,
1740 typename std::enable_if<
1741 !std::is_convertible<
1742 decltype(*std::begin(std::declval<Args>())),
1743 wcstring_ref>::value>::type * = nullptr)
1744 {
1745 for (auto && arg: std::forward<Args>(args))
1746 env_buffer.emplace_back(arg);
1747 return build_env(env_buffer);
1748 }
1749
1750 process_environment(std::initializer_list<string_view> sv) : unicode_env{build_env(sv)} {}
1751 process_environment(std::initializer_list<wstring_view> sv) : unicode_env{build_env(sv)} {}
1752
1753 template<typename Args>
1754 process_environment(Args && args) : unicode_env{build_env(std::forward<Args>(args))}
1755 {
1756 }
1757
1758 error_code error() {return ec;}
1759 error_code ec;
1760 std::vector<environment::key_value_pair> env_buffer;
1761 std::vector<wchar_t> unicode_env;
1762
1763 BOOST_PROCESS_V2_DECL
1764 error_code on_setup(windows::default_launcher & launcher,
1765 const filesystem::path &, const std::wstring &);
1766
1767 #else
1768
1769 template<typename Args>
1770 static
1771 std::vector<const char *> build_env(Args && args,
1772 typename std::enable_if<
1773 std::is_convertible<
1774 decltype(*std::begin(std::declval<Args>())),
1775 cstring_ref>::value>::type * = nullptr)
1776 {
1777 std::vector<const char *> env;
1778 for (auto && e : args)
1779 env.push_back(e.c_str());
1780
1781 env.push_back(nullptr);
1782 return env;
1783 }
1784
1785 template<typename Args>
1786 std::vector<const char *> build_env(Args && args,
1787 typename std::enable_if<
1788 !std::is_convertible<
1789 decltype(*std::begin(std::declval<Args>())),
1790 cstring_ref>::value>::type * = nullptr)
1791 {
1792 std::vector<const char *> env;
1793
1794 for (auto && arg: std::forward<Args>(args))
1795 env_buffer.emplace_back(arg);
1796
1797 for (auto && e : env_buffer)
1798 env.push_back(e.c_str());
1799 env.push_back(nullptr);
1800 return env;
1801 }
1802
1803
1804 process_environment(std::initializer_list<string_view> sv) : env{build_env(sv)} { }
1805
1806 template<typename Args>
1807 process_environment(Args && args) : env(build_env(std::forward<Args>(args)))
1808 {
1809 }
1810
1811
1812 BOOST_PROCESS_V2_DECL
1813 error_code on_setup(posix::default_launcher & launcher,
1814 const filesystem::path &, const char * const *);
1815
1816 std::vector<environment::key_value_pair> env_buffer;
1817 std::vector<const char *> env;
1818
1819 #endif
1820
1821 };
1822
1823
1824
1825 BOOST_PROCESS_V2_END_NAMESPACE
1826
1827
1828 namespace std
1829 {
1830
1831 template<>
1832 struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_view>
1833 {
1834 std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_view kv) const noexcept
1835 {
1836 return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
1837 }
1838 };
1839
1840
1841 template<>
1842 struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::value_view>
1843 {
1844 std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::value_view kv) const noexcept
1845 {
1846 return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
1847 }
1848 };
1849
1850 template<>
1851 struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>
1852 {
1853 std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view kv) const noexcept
1854 {
1855 return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
1856 }
1857 };
1858
1859
1860 template<>
1861 struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key>
1862 {
1863 std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_view kv) const noexcept
1864 {
1865 return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
1866 }
1867 };
1868
1869
1870 template<>
1871 struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::value>
1872 {
1873 std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::value_view kv) const noexcept
1874 {
1875 return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
1876 }
1877 };
1878
1879 template<>
1880 struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
1881 {
1882 std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view kv) const noexcept
1883 {
1884 return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
1885 }
1886 };
1887
1888 }
1889
1890
1891 #endif