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