environment.hpp 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896
  1. //
  2. // process/environment.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2021 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. #ifndef BOOST_PROCESS_V2_ENVIRONMENT_HPP
  10. #define BOOST_PROCESS_V2_ENVIRONMENT_HPP
  11. #include <boost/process/v2/detail/config.hpp>
  12. #include <boost/process/v2/cstring_ref.hpp>
  13. #include <boost/process/v2/detail/utf8.hpp>
  14. #include <boost/type_traits.hpp>
  15. #include <functional>
  16. #include <memory>
  17. #include <numeric>
  18. #if !defined(GENERATING_DOCUMENTATION)
  19. #if defined(BOOST_PROCESS_V2_WINDOWS)
  20. #include <boost/process/v2/detail/environment_win.hpp>
  21. #else
  22. #include <boost/process/v2/detail/environment_posix.hpp>
  23. #endif
  24. #endif
  25. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  26. /// Namespace for information and functions regarding the calling process.
  27. namespace environment
  28. {
  29. #if defined(GENERATING_DOCUMENTATION)
  30. /// A char traits type that reflects the OS rules for string representing environment keys.
  31. /** Can be an alias of std::char_traits. May only be defined for `char` and `wchar_t`.
  32. *
  33. * Windows treats keys as case-insensitive yet perserving. The char traits are made to reflect
  34. * that behaviour.
  35. */
  36. tempalte<typename Char>
  37. using key_char_traits = implementation_defined ;
  38. /// A char traits type that reflects the OS rules for string representing environment values.
  39. /** Can be an alias of std::char_traits. May only be defined for `char` and `wchar_t`.
  40. */
  41. tempalte<typename Char>
  42. using value_char_traits = implementation_defined ;
  43. /// The character type used by the environment. Either `char` or `wchar_t`.
  44. using char_type = implementation_defined ;
  45. /// The equal character in an environment string used to separate key and value.
  46. constexpr char_type equality_sign = implementation_defined;
  47. /// The delimiter in environemtn lists. Commonly used by the `PATH` variable.
  48. constexpr char_type delimiter = implementation_defined;
  49. /// The native handle of an environment. Note that this can be an owning pointer and is generally not thread safe.
  50. using native_handle = implementation_defined;
  51. #endif
  52. /// The iterator used by a value or value_view to iterator through environments that are lists.
  53. struct value_iterator
  54. {
  55. using string_view_type = basic_string_view<char_type, value_char_traits<char_type>>;
  56. using difference_type = int;
  57. using reference = string_view_type;
  58. using iterator_category = std::forward_iterator_tag;
  59. value_iterator & operator++()
  60. {
  61. const auto delim = view_.find(delimiter);
  62. if (delim != string_view_type::npos)
  63. view_ = view_.substr(delim + 1);
  64. else
  65. view_ = view_.substr(view_.size());
  66. return *this;
  67. }
  68. value_iterator operator++(int)
  69. {
  70. auto last = *this;
  71. ++(*this);
  72. return last;
  73. }
  74. string_view_type operator*() const
  75. {
  76. const auto delim = view_.find(delimiter);
  77. if (delim == string_view_type::npos)
  78. return view_;
  79. else
  80. return view_.substr(0, delim);
  81. }
  82. value_iterator() = default;
  83. value_iterator(const value_iterator & ) = default;
  84. value_iterator(string_view_type view, std::size_t offset = 0u) : view_(view.substr(offset))
  85. {
  86. }
  87. friend bool operator==(const value_iterator & l, const value_iterator & r) { return l.view_ == r.view_; }
  88. friend bool operator!=(const value_iterator & l, const value_iterator & r) { return l.view_ != r.view_; }
  89. private:
  90. string_view_type view_;
  91. };
  92. /// A view type for a key of an environment
  93. struct key_view
  94. {
  95. using value_type = char_type;
  96. using traits_type = key_char_traits<char_type>;
  97. using string_view_type = basic_string_view<char_type, traits_type>;
  98. using string_type = std::basic_string<char_type, key_char_traits<char_type>>;
  99. key_view() noexcept = default;
  100. key_view( const key_view& p ) = default;
  101. key_view( key_view&& p ) noexcept = default;
  102. template<typename Source,
  103. typename = typename std::enable_if<is_constructible<string_view_type, Source>::value>::type>
  104. key_view( const Source& source ) : value_(source) {}
  105. key_view( const char_type * p) : value_(p) {}
  106. key_view( char_type * p) : value_(p) {}
  107. ~key_view() = default;
  108. key_view& operator=( const key_view& p ) = default;
  109. key_view& operator=( key_view&& p ) noexcept = default;
  110. key_view& operator=( string_view_type source )
  111. {
  112. value_ = source;
  113. return *this;
  114. }
  115. void swap( key_view& other ) noexcept
  116. {
  117. std::swap(value_, other.value_);
  118. }
  119. string_view_type native() const noexcept {return value_;}
  120. operator string_view_type() const {return native();}
  121. int compare( const key_view& p ) const noexcept {return value_.compare(p.value_);}
  122. int compare( string_view_type str ) const {return value_.compare(str);}
  123. int compare( const value_type* s ) const {return value_.compare(s);}
  124. template< class CharT, class Traits = std::char_traits<CharT>,
  125. class Alloc = std::allocator<CharT> >
  126. std::basic_string<CharT,Traits,Alloc>
  127. basic_string( const Alloc& alloc = Alloc()) const
  128. {
  129. return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
  130. value_.data(), value_.size(), alloc);
  131. }
  132. std::string string() const {return basic_string<char>();}
  133. std::wstring wstring() const {return basic_string<wchar_t>();}
  134. string_type native_string() const
  135. {
  136. return basic_string<char_type, key_char_traits<char_type>>();
  137. }
  138. friend bool operator==(key_view l, key_view r) { return l.value_ == r.value_; }
  139. friend bool operator!=(key_view l, key_view r) { return l.value_ != r.value_; }
  140. friend bool operator<=(key_view l, key_view r) { return l.value_ <= r.value_; }
  141. friend bool operator>=(key_view l, key_view r) { return l.value_ >= r.value_; }
  142. friend bool operator< (key_view l, key_view r) { return l.value_ < r.value_; }
  143. friend bool operator> (key_view l, key_view r) { return l.value_ > r.value_; }
  144. bool empty() const {return value_.empty(); }
  145. template< class CharT, class Traits >
  146. friend std::basic_ostream<CharT,Traits>&
  147. operator<<( std::basic_ostream<CharT,Traits>& os, const key_view& p )
  148. {
  149. os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
  150. return os;
  151. }
  152. template< class CharT, class Traits >
  153. friend std::basic_istream<CharT,Traits>&
  154. operator>>( std::basic_istream<CharT,Traits>& is, key_view& p )
  155. {
  156. std::basic_string<CharT, Traits> t;
  157. is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
  158. p = t;
  159. return is;
  160. }
  161. const value_type * data() const {return value_.data(); }
  162. std::size_t size() const {return value_.size(); }
  163. private:
  164. string_view_type value_;
  165. };
  166. /// A view for a value in an environment
  167. struct value_view
  168. {
  169. using value_type = char_type;
  170. using string_view_type = basic_cstring_ref<char_type, value_char_traits<char_type>>;
  171. using string_type = std::basic_string<char_type, value_char_traits<char_type>>;
  172. using traits_type = value_char_traits<char_type>;
  173. value_view() noexcept = default;
  174. value_view( const value_view& p ) = default;
  175. value_view( value_view&& p ) noexcept = default;
  176. template<typename Source, typename = typename std::enable_if<is_constructible<string_view_type, Source>::value>::type>
  177. value_view( const Source& source ) : value_(source) {}
  178. value_view( const char_type * p) : value_(p) {}
  179. value_view( char_type * p) : value_(p) {}
  180. ~value_view() = default;
  181. value_view& operator=( const value_view& p ) = default;
  182. value_view& operator=( value_view&& p ) noexcept = default;
  183. value_view& operator=( string_view_type source )
  184. {
  185. value_ = source;
  186. return *this;
  187. }
  188. void swap( value_view& other ) noexcept
  189. {
  190. std::swap(value_, other.value_);
  191. }
  192. string_view_type native() const noexcept {return value_;}
  193. operator string_view_type() const {return native();}
  194. operator typename string_view_type::string_view_type() const {return value_; }
  195. int compare( const value_view& p ) const noexcept {return value_.compare(p.value_);}
  196. int compare( string_view_type str ) const {return value_.compare(str);}
  197. int compare( const value_type* s ) const {return value_.compare(s);}
  198. template< class CharT, class Traits = std::char_traits<CharT>,
  199. class Alloc = std::allocator<CharT> >
  200. std::basic_string<CharT,Traits,Alloc>
  201. basic_string( const Alloc& alloc = Alloc() ) const
  202. {
  203. return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
  204. value_.data(), value_.size(), alloc);
  205. }
  206. std::string string() const {return basic_string<char>();}
  207. std::wstring wstring() const {return basic_string<wchar_t>();}
  208. string_type native_string() const
  209. {
  210. return basic_string<char_type, value_char_traits<char_type>>();
  211. }
  212. bool empty() const {return value_.empty(); }
  213. friend bool operator==(value_view l, value_view r) { return l.value_ == r.value_; }
  214. friend bool operator!=(value_view l, value_view r) { return l.value_ != r.value_; }
  215. friend bool operator<=(value_view l, value_view r) { return l.value_ <= r.value_; }
  216. friend bool operator>=(value_view l, value_view r) { return l.value_ >= r.value_; }
  217. friend bool operator< (value_view l, value_view r) { return l.value_ < r.value_; }
  218. friend bool operator> (value_view l, value_view r) { return l.value_ > r.value_; }
  219. template< class CharT, class Traits >
  220. friend std::basic_ostream<CharT,Traits>&
  221. operator<<( std::basic_ostream<CharT,Traits>& os, const value_view& p )
  222. {
  223. os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
  224. return os;
  225. }
  226. template< class CharT, class Traits >
  227. friend std::basic_istream<CharT,Traits>&
  228. operator>>( std::basic_istream<CharT,Traits>& is, value_view& p )
  229. {
  230. std::basic_string<CharT, Traits> t;
  231. is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
  232. p = t;
  233. return is;
  234. }
  235. value_iterator begin() const {return value_iterator(value_.data());}
  236. value_iterator end() const {return value_iterator(value_.data() , value_.size());}
  237. const char_type * c_str() {return value_.c_str(); }
  238. const value_type * data() const {return value_.data(); }
  239. std::size_t size() const {return value_.size(); }
  240. private:
  241. string_view_type value_;
  242. };
  243. /// A view for a key value pair in an environment
  244. struct key_value_pair_view
  245. {
  246. using value_type = char_type;
  247. using string_type = std::basic_string<char_type>;
  248. using string_view_type = basic_cstring_ref<char_type>;
  249. using traits_type = std::char_traits<char_type>;
  250. key_value_pair_view() noexcept = default;
  251. key_value_pair_view( const key_value_pair_view& p ) = default;
  252. key_value_pair_view( key_value_pair_view&& p ) noexcept = default;
  253. template<typename Source,
  254. typename = typename std::enable_if<is_constructible<string_view_type, Source>::value>::type>
  255. key_value_pair_view( const Source& source ) : value_(source) {}
  256. key_value_pair_view( const char_type * p) : value_(p) {}
  257. key_value_pair_view( char_type * p) : value_(p) {}
  258. ~key_value_pair_view() = default;
  259. key_value_pair_view& operator=( const key_value_pair_view& p ) = default;
  260. key_value_pair_view& operator=( key_value_pair_view&& p ) noexcept = default;
  261. void swap( key_value_pair_view& other ) noexcept
  262. {
  263. std::swap(value_, other.value_);
  264. }
  265. string_view_type native() const noexcept {return value_;}
  266. operator string_view_type() const {return native();}
  267. operator typename string_view_type::string_view_type() const {return value_; }
  268. int compare( key_value_pair_view p ) const noexcept
  269. {
  270. const auto c = key().compare(p.key());
  271. if (c != 0)
  272. return c;
  273. return value().compare(p.value());
  274. }
  275. int compare( const string_type& str ) const
  276. {
  277. return compare(key_value_pair_view(str));
  278. }
  279. int compare( string_view_type str ) const
  280. {
  281. string_type st(str.data(), str.size());
  282. return compare(st);
  283. }
  284. int compare( const value_type* s ) const
  285. {
  286. return compare(key_value_pair_view(s));
  287. }
  288. template< class CharT, class Traits = std::char_traits<CharT>, class Alloc = std::allocator<CharT> >
  289. std::basic_string<CharT,Traits,Alloc>
  290. basic_string( const Alloc& alloc = Alloc()) const
  291. {
  292. return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(value_.begin(), value_.size(), alloc);
  293. }
  294. std::string string() const {return basic_string<char>();}
  295. std::wstring wstring() const {return basic_string<wchar_t>();}
  296. string_type native_string() const
  297. {
  298. return basic_string<char_type>();
  299. }
  300. bool empty() const {return value_.empty(); }
  301. key_view key() const
  302. {
  303. auto eq = value_.find(equality_sign);
  304. if (eq == 0)
  305. {
  306. auto eq2 = value_.find(equality_sign, 1);
  307. if (eq2 != string_type::npos)
  308. eq = eq2;
  309. }
  310. const auto res = native().substr(0, eq == string_view_type::npos ? value_.size() : eq);
  311. return key_view::string_view_type(res.data(), res.size());
  312. }
  313. value_view value() const
  314. {
  315. auto eq = value_.find(equality_sign);
  316. if (eq == 0)
  317. {
  318. auto eq2 = value_.find(equality_sign, 1);
  319. if (eq2 != string_type::npos)
  320. eq = eq2;
  321. }
  322. return environment::value_view(native().substr(eq + 1));
  323. }
  324. friend bool operator==(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) == 0; }
  325. friend bool operator!=(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) != 0; }
  326. friend bool operator<=(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) <= 0; }
  327. friend bool operator>=(key_value_pair_view l, key_value_pair_view r) { return l.compare(r) >= 0; }
  328. friend bool operator< (key_value_pair_view l, key_value_pair_view r) { return l.compare(r) < 0; }
  329. friend bool operator> (key_value_pair_view l, key_value_pair_view r) { return l.compare(r) > 0; }
  330. template< class CharT, class Traits >
  331. friend std::basic_ostream<CharT,Traits>&
  332. operator<<( std::basic_ostream<CharT,Traits>& os, const key_value_pair_view& p )
  333. {
  334. os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
  335. return os;
  336. }
  337. template< class CharT, class Traits >
  338. friend std::basic_istream<CharT,Traits>&
  339. operator>>( std::basic_istream<CharT,Traits>& is, key_value_pair_view& p )
  340. {
  341. std::basic_string<CharT, Traits> t;
  342. is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
  343. p = t;
  344. return is;
  345. }
  346. template<std::size_t Idx>
  347. inline auto get() const -> typename conditional<Idx == 0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_view,
  348. BOOST_PROCESS_V2_NAMESPACE::environment::value_view>::type;
  349. const value_type * c_str() const noexcept
  350. {
  351. return value_.data();
  352. }
  353. const value_type * data() const {return value_.data(); }
  354. std::size_t size() const {return value_.size(); }
  355. private:
  356. string_view_type value_;
  357. };
  358. template<>
  359. inline key_view key_value_pair_view::get<0u>() const
  360. {
  361. return key();
  362. }
  363. template<>
  364. inline value_view key_value_pair_view::get<1u>() const
  365. {
  366. return value();
  367. }
  368. namespace detail
  369. {
  370. template<typename Char>
  371. std::size_t hash_step(std::size_t prev, Char c, std::char_traits<Char>)
  372. {
  373. return prev ^ (c << 1);
  374. }
  375. }
  376. inline std::size_t hash_value(const key_view & value)
  377. {
  378. std::size_t hash = 0u;
  379. for (auto c = value.data(); *c != *v2::detail::null_char_(*c); c++)
  380. hash = detail::hash_step(hash, *c, key_view::traits_type{});
  381. return hash ;
  382. }
  383. inline std::size_t hash_value(const BOOST_PROCESS_V2_NAMESPACE::environment::value_view & value)
  384. {
  385. std::size_t hash = 0u;
  386. for (auto c = value.data(); *c != *v2::detail::null_char_(*c); c++)
  387. hash = detail::hash_step(hash, *c, value_view::traits_type{});
  388. return hash ;
  389. }
  390. inline std::size_t hash_value(const BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view & value)
  391. {
  392. std::size_t hash = 0u;
  393. for (auto c = value.data(); *c != *v2::detail::null_char_(*c); c++)
  394. hash = detail::hash_step(hash, *c, key_value_pair_view::traits_type{});
  395. return hash ;
  396. }
  397. /// A class representing a key within an environment.
  398. struct key
  399. {
  400. using value_type = char_type;
  401. using traits_type = key_char_traits<char_type>;
  402. using string_type = std::basic_string<char_type, traits_type>;
  403. using string_view_type = basic_string_view<char_type, traits_type>;
  404. key() {}
  405. key( const key& p ) = default;
  406. key( key&& p ) noexcept = default;
  407. key( const string_type& source ) : value_(source) {}
  408. key( string_type&& source ) : value_(std::move(source)) {}
  409. key( const value_type * raw ) : value_(raw) {}
  410. key( value_type * raw ) : value_(raw) {}
  411. explicit key(key_view kv) : value_(kv.native_string()) {}
  412. template< class Source >
  413. key( const Source& source,
  414. decltype(std::declval<Source>().data()) = nullptr,
  415. decltype(std::declval<Source>().size()) = 0u)
  416. : value_(
  417. BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  418. source.data(), source.size()))
  419. {
  420. }
  421. key(const typename conditional<is_same<value_type, char>::value, wchar_t, char>::type * raw)
  422. : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  423. raw, std::char_traits<std::decay<std::remove_pointer<decltype(raw)>::type>::type>::length(raw)))
  424. {
  425. }
  426. template< class InputIt >
  427. key( InputIt first, InputIt last)
  428. : key(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last))
  429. {
  430. }
  431. ~key() = default;
  432. key& operator=( const key& p ) = default;
  433. key& operator=( key&& p )
  434. {
  435. value_ = std::move(p.value_);
  436. return *this;
  437. }
  438. key& operator=( string_type&& source )
  439. {
  440. value_ = std::move(source);
  441. return *this;
  442. }
  443. template< class Source >
  444. key& operator=( const Source& source )
  445. {
  446. value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(source.data(), source.size());
  447. return *this;
  448. }
  449. key& assign( string_type&& source )
  450. {
  451. value_ = std::move(source);
  452. return *this;
  453. }
  454. template< class Source >
  455. key& assign( const Source& source )
  456. {
  457. value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(source.data(), source.size());
  458. return *this;
  459. }
  460. template< class InputIt >
  461. key& assign( InputIt first, InputIt last )
  462. {
  463. return assign(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last));
  464. }
  465. void clear() {value_.clear();}
  466. void swap( key& other ) noexcept
  467. {
  468. std::swap(value_, other.value_);
  469. }
  470. const value_type* c_str() const noexcept {return value_.c_str();}
  471. const string_type& native() const noexcept {return value_;}
  472. string_view_type native_view() const noexcept {return value_;}
  473. operator string_type() const {return native();}
  474. operator string_view_type() const {return native_view();}
  475. int compare( const key& p ) const noexcept {return value_.compare(p.value_);}
  476. int compare( const string_type& str ) const {return value_.compare(str);}
  477. int compare( string_view_type str ) const {return -str.compare(value_);}
  478. int compare( const value_type* s ) const {return value_.compare(s);}
  479. template< class CharT, class Traits = std::char_traits<CharT>,
  480. class Alloc = std::allocator<CharT> >
  481. std::basic_string<CharT,Traits,Alloc>
  482. basic_string( const Alloc& alloc = Alloc()) const
  483. {
  484. return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
  485. value_.data(), value_.size(), alloc);
  486. }
  487. std::string string() const {return basic_string<char>();}
  488. std::wstring wstring() const {return basic_string<wchar_t>();}
  489. const string_type & native_string() const
  490. {
  491. return value_;
  492. }
  493. bool empty() const {return value_.empty(); }
  494. friend bool operator==(const key & l, const key & r) { return l.value_ == r.value_; }
  495. friend bool operator!=(const key & l, const key & r) { return l.value_ != r.value_; }
  496. friend bool operator<=(const key & l, const key & r) { return l.value_ <= r.value_; }
  497. friend bool operator>=(const key & l, const key & r) { return l.value_ >= r.value_; }
  498. friend bool operator< (const key & l, const key & r) { return l.value_ < r.value_; }
  499. friend bool operator> (const key & l, const key & r) { return l.value_ > r.value_; }
  500. template< class CharT, class Traits >
  501. friend std::basic_ostream<CharT,Traits>&
  502. operator<<( std::basic_ostream<CharT,Traits>& os, const key& p )
  503. {
  504. os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
  505. return os;
  506. }
  507. template< class CharT, class Traits >
  508. friend std::basic_istream<CharT,Traits>&
  509. operator>>( std::basic_istream<CharT,Traits>& is, key& p )
  510. {
  511. std::basic_string<CharT, Traits> t;
  512. is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
  513. p = t;
  514. return is;
  515. }
  516. const value_type * data() const {return value_.data(); }
  517. std::size_t size() const {return value_.size(); }
  518. private:
  519. string_type value_;
  520. };
  521. #if !defined(GENERATING_DOCUMENTATION)
  522. template<typename T, typename U>
  523. typename std::enable_if<
  524. ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
  525. std::is_convertible<const U &, key_view>::value)
  526. ||
  527. ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
  528. std::is_convertible<const T & , key_view>::value),
  529. bool>::type
  530. operator==(const T &l, const U & r) { return key_view(l) == key_view(r); }
  531. template<typename T, typename U>
  532. typename std::enable_if<
  533. ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
  534. std::is_convertible<const U &, key_view>::value)
  535. ||
  536. ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
  537. std::is_convertible<const T & , key_view>::value),
  538. bool>::type
  539. operator!=(const T &l, const U & r) { return key_view(l) != key_view(r); }
  540. template<typename T, typename U>
  541. typename std::enable_if<
  542. ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
  543. std::is_convertible<const U &, key_view>::value)
  544. ||
  545. ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
  546. std::is_convertible<const T & , key_view>::value),
  547. bool>::type
  548. operator<=(const T &l, const U & r) { return key_view(l) <= key_view(r); }
  549. template<typename T, typename U>
  550. typename std::enable_if<
  551. ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
  552. std::is_convertible<const U &, key_view>::value)
  553. ||
  554. ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
  555. std::is_convertible<const T & , key_view>::value),
  556. bool>::type
  557. operator <(const T &l, const U & r) { return key_view(l) < key_view(r); }
  558. template<typename T, typename U>
  559. typename std::enable_if<
  560. ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
  561. std::is_convertible<const U &, key_view>::value)
  562. ||
  563. ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
  564. std::is_convertible<const T & , key_view>::value),
  565. bool>::type
  566. operator>=(const T &l, const U & r) { return key_view(l) >= key_view(r); }
  567. template<typename T, typename U>
  568. typename std::enable_if<
  569. ((std::is_same<T, key>::value || std::is_same<T, key_view>::value) &&
  570. std::is_convertible<const U &, key_view>::value)
  571. ||
  572. ((std::is_same<U, key>::value || std::is_same<U, key_view>::value) &&
  573. std::is_convertible<const T & , key_view>::value),
  574. bool>::type
  575. operator >(const T &l, const U & r) { return key_view(l) > key_view(r); }
  576. #else
  577. bool operator==(const value_view &, const value_view);
  578. bool operator!=(const value_view &, const value_view);
  579. bool operator<=(const value_view &, const value_view);
  580. bool operator< (const value_view &, const value_view);
  581. bool operator> (const value_view &, const value_view);
  582. bool operator>=(const value_view &, const value_view);
  583. #endif
  584. struct value
  585. {
  586. using value_type = char_type;
  587. using traits_type = value_char_traits<char_type>;
  588. using string_type = std::basic_string<char_type, traits_type>;
  589. using string_view_type = basic_cstring_ref<char_type, traits_type>;
  590. value() {}
  591. value( const value& p ) = default;
  592. value( const string_type& source ) : value_(source) {}
  593. value( string_type&& source ) : value_(std::move(source)) {}
  594. value( const value_type * raw ) : value_(raw) {}
  595. value( value_type * raw ) : value_(raw) {}
  596. explicit value(value_view kv) : value_(kv.c_str()) {}
  597. template< class Source >
  598. value( const Source& source,
  599. decltype(std::declval<Source>().data()) = nullptr,
  600. decltype(std::declval<Source>().size()) = 0u)
  601. : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  602. source.data(), source.size()))
  603. {
  604. }
  605. value(const typename conditional<is_same<value_type, char>::value, wchar_t, char>::type * raw)
  606. : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  607. raw, std::char_traits<std::decay<std::remove_pointer<decltype(raw)>::type>::type>::length(raw)))
  608. {
  609. }
  610. template< class InputIt >
  611. value( InputIt first, InputIt last)
  612. : value(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last))
  613. {
  614. }
  615. ~value() = default;
  616. value& operator=( const value& p ) = default;
  617. value& operator=( value&& p )
  618. {
  619. value_ = std::move(p.value_);
  620. return *this;
  621. }
  622. value& operator=( string_type&& source )
  623. {
  624. value_ = std::move(source);
  625. return *this;
  626. }
  627. template< class Source >
  628. value& operator=( const Source& source )
  629. {
  630. value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  631. source.data(), source.size);
  632. return *this;
  633. }
  634. value& assign( string_type&& source )
  635. {
  636. value_ = std::move(source);
  637. return *this;
  638. }
  639. template< class Source >
  640. value& assign( const Source& source )
  641. {
  642. value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  643. source.data(), source.size());
  644. return *this;
  645. }
  646. template< class InputIt >
  647. value& assign( InputIt first, InputIt last )
  648. {
  649. return assign(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last));
  650. }
  651. void push_back(const value & sv)
  652. {
  653. (value_ += delimiter) += sv;
  654. }
  655. void clear() {value_.clear();}
  656. void swap( value& other ) noexcept
  657. {
  658. std::swap(value_, other.value_);
  659. }
  660. const value_type* c_str() const noexcept {return value_.c_str();}
  661. const string_type& native() const noexcept {return value_;}
  662. string_view_type native_view() const noexcept {return value_;}
  663. operator string_type() const {return native();}
  664. operator string_view_type() const {return native_view();}
  665. operator typename string_view_type::string_view_type() const {return value_; }
  666. int compare( const value& p ) const noexcept {return value_.compare(p.value_);}
  667. int compare( const string_type& str ) const {return value_.compare(str);}
  668. int compare( string_view_type str ) const {return -str.compare(value_);}
  669. int compare( const value_type* s ) const {return value_.compare(s);}
  670. template< class CharT, class Traits = std::char_traits<CharT>,
  671. class Alloc = std::allocator<CharT> >
  672. std::basic_string<CharT,Traits,Alloc>
  673. basic_string( const Alloc& alloc = Alloc()) const
  674. {
  675. return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(
  676. value_.data(), value_.size(),alloc);
  677. }
  678. std::string string() const {return basic_string<char>();}
  679. std::wstring wstring() const {return basic_string<wchar_t>();}
  680. const string_type & native_string() const
  681. {
  682. return value_;
  683. }
  684. bool empty() const {return value_.empty(); }
  685. friend bool operator==(const value & l, const value & r) { return l.value_ == r.value_; }
  686. friend bool operator!=(const value & l, const value & r) { return l.value_ != r.value_; }
  687. friend bool operator<=(const value & l, const value & r) { return l.value_ <= r.value_; }
  688. friend bool operator>=(const value & l, const value & r) { return l.value_ >= r.value_; }
  689. friend bool operator< (const value & l, const value & r) { return l.value_ < r.value_; }
  690. friend bool operator> (const value & l, const value & r) { return l.value_ > r.value_; }
  691. template< class CharT, class Traits >
  692. friend std::basic_ostream<CharT,Traits>&
  693. operator<<( std::basic_ostream<CharT,Traits>& os, const value& p )
  694. {
  695. os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
  696. return os;
  697. }
  698. template< class CharT, class Traits >
  699. friend std::basic_istream<CharT,Traits>&
  700. operator>>( std::basic_istream<CharT,Traits>& is, value& p )
  701. {
  702. std::basic_string<CharT, Traits> t;
  703. is >> BOOST_PROCESS_V2_NAMESPACE::quoted(t);
  704. p = t;
  705. return is;
  706. }
  707. value_iterator begin() const {return value_iterator(value_.data());}
  708. value_iterator end() const {return value_iterator(value_.data(), value_.size());}
  709. const value_type * data() const {return value_.data(); }
  710. std::size_t size() const {return value_.size(); }
  711. private:
  712. string_type value_;
  713. };
  714. #if !defined(GENERATING_DOCUMENTATION)
  715. template<typename T, typename U>
  716. typename std::enable_if<
  717. ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
  718. std::is_convertible<const U &, value_view>::value)
  719. ||
  720. ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
  721. std::is_convertible<const T & , value_view>::value),
  722. bool>::type
  723. operator==(const T &l, const U & r) { return value_view(l) == value_view(r); }
  724. template<typename T, typename U>
  725. typename std::enable_if<
  726. ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
  727. std::is_convertible<const U &, value_view>::value)
  728. ||
  729. ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
  730. std::is_convertible<const T & , value_view>::value),
  731. bool>::type
  732. operator!=(const T &l, const U & r) { return value_view(l) != value_view(r); }
  733. template<typename T, typename U>
  734. typename std::enable_if<
  735. ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
  736. std::is_convertible<const U &, value_view>::value)
  737. ||
  738. ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
  739. std::is_convertible<const T & , value_view>::value),
  740. bool>::type
  741. operator<=(const T &l, const U & r) { return value_view(l) <= value_view(r); }
  742. template<typename T, typename U>
  743. typename std::enable_if<
  744. ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
  745. std::is_convertible<const U &, value_view>::value)
  746. ||
  747. ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
  748. std::is_convertible<const T & , value_view>::value),
  749. bool>::type
  750. operator <(const T &l, const U & r) { return value_view(l) < value_view(r); }
  751. template<typename T, typename U>
  752. typename std::enable_if<
  753. ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
  754. std::is_convertible<const U &, value_view>::value)
  755. ||
  756. ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
  757. std::is_convertible<const T & , value_view>::value),
  758. bool>::type
  759. operator>=(const T &l, const U & r) { return value_view(l) >= value_view(r); }
  760. template<typename T, typename U>
  761. typename std::enable_if<
  762. ((std::is_same<T, value>::value || std::is_same<T, value_view>::value) &&
  763. std::is_convertible<const U &, value_view>::value)
  764. ||
  765. ((std::is_same<U, value>::value || std::is_same<U, value_view>::value) &&
  766. std::is_convertible<const T & , value_view>::value),
  767. bool>::type
  768. operator >(const T &l, const U & r) { return value_view(l) > value_view(r); }
  769. #else
  770. bool operator==(const value_view &, const value_view);
  771. bool operator!=(const value_view &, const value_view);
  772. bool operator<=(const value_view &, const value_view);
  773. bool operator< (const value_view &, const value_view);
  774. bool operator> (const value_view &, const value_view);
  775. bool operator>=(const value_view &, const value_view);
  776. #endif
  777. struct key_value_pair
  778. {
  779. using value_type = char_type;
  780. using traits_type = std::char_traits<char_type>;
  781. using string_type = std::basic_string<char_type>;
  782. using string_view_type = basic_cstring_ref<char_type>;
  783. key_value_pair() {}
  784. key_value_pair( const key_value_pair& p ) = default;
  785. key_value_pair( key_value_pair&& p ) noexcept = default;
  786. key_value_pair(key_view key, value_view value) : value_(key.basic_string<char_type, traits_type>() + equality_sign +
  787. value.basic_string<char_type, traits_type>()) {}
  788. key_value_pair(key_view key, std::initializer_list<basic_string_view<char_type>> values)
  789. {
  790. const auto sz = std::accumulate(values.begin(), values.end(),
  791. key.size(), [](std::size_t sz, const basic_string_view<char_type> & str) { return sz + str.size() + 1;});
  792. value_.reserve(sz);
  793. value_.append(key.data(), key.size());
  794. value_ += equality_sign;
  795. for (auto & value : values)
  796. {
  797. if (value_.back() != equality_sign)
  798. value_ += delimiter;
  799. value_.append(value.data(), value.size());
  800. }
  801. }
  802. key_value_pair( const string_type& source ) : value_(source) {}
  803. key_value_pair( string_type&& source ) : value_(std::move(source)) {}
  804. key_value_pair( const value_type * raw ) : value_(raw) {}
  805. key_value_pair( value_type * raw ) : value_(raw) {}
  806. explicit key_value_pair(key_value_pair_view kv) : value_(kv.c_str()) {}
  807. template< class Source >
  808. key_value_pair( const Source& source,
  809. decltype(std::declval<Source>().data()) = nullptr,
  810. decltype(std::declval<Source>().size()) = 0u)
  811. : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  812. source.data(), source.size()))
  813. {
  814. }
  815. template< typename Key,
  816. typename Value >
  817. key_value_pair(
  818. const std::pair<Key, Value> & kv/*,
  819. typename std::enable_if<std::is_constructible<struct key, Key >::value &&
  820. std::is_constructible<struct value, Value>::value
  821. >::type = 0*/) : value_(((struct key)(kv.first)).basic_string<char_type, traits_type>() + equality_sign
  822. + ((struct value)(kv.second)).basic_string<char_type, traits_type>())
  823. {}
  824. key_value_pair(const typename conditional<is_same<value_type, char>::value, wchar_t, char>::type * raw)
  825. : value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  826. raw,
  827. std::char_traits<std::decay<std::remove_pointer<decltype(raw)>::type>::type>::length(raw)))
  828. {
  829. }
  830. template< class InputIt , typename std::iterator_traits<InputIt>::iterator_category>
  831. key_value_pair( InputIt first, InputIt last )
  832. : key_value_pair(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last))
  833. {
  834. }
  835. ~key_value_pair() = default;
  836. key_value_pair& operator=( const key_value_pair& p ) = default;
  837. key_value_pair& operator=( key_value_pair&& p )
  838. {
  839. value_ = std::move(p.value_);
  840. return *this;
  841. }
  842. key_value_pair& operator=( string_type&& source )
  843. {
  844. value_ = std::move(source);
  845. return *this;
  846. }
  847. template< class Source >
  848. key_value_pair& operator=( const Source& source )
  849. {
  850. value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  851. source.data(), source.size());
  852. return *this;
  853. }
  854. key_value_pair& assign( string_type&& source )
  855. {
  856. value_ = std::move(source);
  857. return *this;
  858. }
  859. template< class Source >
  860. key_value_pair& assign( const Source& source )
  861. {
  862. value_ = BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
  863. source.data(), source.size());
  864. return *this;
  865. }
  866. template< class InputIt >
  867. key_value_pair& assign( InputIt first, InputIt last )
  868. {
  869. return assign(std::basic_string<typename std::iterator_traits<typename std::decay<InputIt>::type>::value_type>(first, last));
  870. }
  871. void clear() {value_.clear();}
  872. void swap( key_value_pair& other ) noexcept
  873. {
  874. std::swap(value_, other.value_);
  875. }
  876. const value_type* c_str() const noexcept {return value_.c_str();}
  877. const string_type& native() const noexcept {return value_;}
  878. string_view_type native_view() const noexcept {return value_;}
  879. operator string_type() const {return native();}
  880. operator string_view_type() const {return native_view();}
  881. operator typename string_view_type::string_view_type() const {return native_view();}
  882. operator key_value_pair_view() const {return native_view();}
  883. int compare( const key_value_pair& p ) const noexcept
  884. {
  885. return key_value_pair_view(*this).compare(key_value_pair_view(p));
  886. }
  887. int compare( const string_type& str ) const
  888. {
  889. return key_value_pair_view(*this).compare(str);
  890. }
  891. int compare( string_view_type str ) const
  892. {
  893. return key_value_pair_view(*this).compare(str);
  894. }
  895. int compare( const value_type* s ) const
  896. {
  897. return key_value_pair_view(*this).compare(s);
  898. }
  899. template< class CharT, class Traits = std::char_traits<CharT>, class Alloc = std::allocator<CharT> >
  900. std::basic_string<CharT,Traits,Alloc>
  901. basic_string( const Alloc& alloc = Alloc() ) const
  902. {
  903. return BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<CharT, Traits>(value_.data(), value_.size(), alloc);
  904. }
  905. std::string string() const {return basic_string<char>();}
  906. std::wstring wstring() const {return basic_string<wchar_t>();}
  907. const string_type & native_string() const
  908. {
  909. return value_;
  910. }
  911. friend bool operator==(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) == 0; }
  912. friend bool operator!=(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) != 0; }
  913. friend bool operator<=(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) <= 0; }
  914. friend bool operator>=(const key_value_pair & l, const key_value_pair & r) { return l.compare(r) >= 0; }
  915. friend bool operator< (const key_value_pair & l, const key_value_pair & r) { return l.compare(r) < 0; }
  916. friend bool operator> (const key_value_pair & l, const key_value_pair & r) { return l.compare(r) > 0; }
  917. bool empty() const {return value_.empty(); }
  918. struct key_view key() const
  919. {
  920. auto eq = value_.find(equality_sign);
  921. if (eq == 0)
  922. {
  923. auto eq2 = value_.find(equality_sign, 1);
  924. if (eq2 != string_type::npos)
  925. eq = eq2;
  926. }
  927. const auto k = native_view().substr(0, eq);
  928. return BOOST_PROCESS_V2_NAMESPACE::environment::key_view::string_view_type (k.data(), k.size());
  929. }
  930. struct value_view value() const
  931. {
  932. auto eq = value_.find(equality_sign);
  933. if (eq == 0)
  934. {
  935. auto eq2 = value_.find(equality_sign, 1);
  936. if (eq2 != string_type::npos)
  937. eq = eq2;
  938. }
  939. return value_view::string_view_type(native_view().substr(eq + 1));
  940. }
  941. template< class CharT, class Traits >
  942. friend std::basic_ostream<CharT,Traits>&
  943. operator<<( std::basic_ostream<CharT,Traits>& os, const key_value_pair& p )
  944. {
  945. os << BOOST_PROCESS_V2_NAMESPACE::quoted(p.basic_string<CharT,Traits>());
  946. return os;
  947. }
  948. template< class CharT, class Traits >
  949. friend std::basic_istream<CharT,Traits>&
  950. operator>>( std::basic_istream<CharT,Traits>& is, key_value_pair& p )
  951. {
  952. is >> BOOST_PROCESS_V2_NAMESPACE::quoted(p.value_);
  953. return is;
  954. }
  955. const value_type * data() const {return value_.data(); }
  956. std::size_t size() const {return value_.size(); }
  957. template<std::size_t Idx>
  958. inline auto get() const
  959. -> typename conditional<Idx == 0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_view,
  960. BOOST_PROCESS_V2_NAMESPACE::environment::value_view>::type;
  961. private:
  962. string_type value_;
  963. };
  964. #if !defined(GENERATING_DOCUMENTATION)
  965. template<typename T, typename U>
  966. typename std::enable_if<
  967. ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
  968. std::is_convertible<const U &, key_value_pair_view>::value)
  969. ||
  970. ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
  971. std::is_convertible<const T & , key_value_pair_view>::value),
  972. bool>::type
  973. operator==(const T &l, const U & r) { return key_value_pair_view(l) == key_value_pair_view(r); }
  974. template<typename T, typename U>
  975. typename std::enable_if<
  976. ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
  977. std::is_convertible<const U &, key_value_pair_view>::value)
  978. ||
  979. ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
  980. std::is_convertible<const T & , key_value_pair_view>::value),
  981. bool>::type
  982. operator!=(const T &l, const U & r) { return key_value_pair_view(l) != key_value_pair_view(r); }
  983. template<typename T, typename U>
  984. typename std::enable_if<
  985. ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
  986. std::is_convertible<const U &, key_value_pair_view>::value)
  987. ||
  988. ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
  989. std::is_convertible<const T & , key_value_pair_view>::value),
  990. bool>::type
  991. operator<=(const T &l, const U & r) { return key_value_pair_view(l) <= key_value_pair_view(r); }
  992. template<typename T, typename U>
  993. typename std::enable_if<
  994. ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
  995. std::is_convertible<const U &, key_value_pair_view>::value)
  996. ||
  997. ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
  998. std::is_convertible<const T & , key_value_pair_view>::value),
  999. bool>::type
  1000. operator <(const T &l, const U & r) { return key_value_pair_view(l) < key_value_pair_view(r); }
  1001. template<typename T, typename U>
  1002. typename std::enable_if<
  1003. ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
  1004. std::is_convertible<const U &, key_value_pair_view>::value)
  1005. ||
  1006. ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
  1007. std::is_convertible<const T & , key_value_pair_view>::value),
  1008. bool>::type
  1009. operator>=(const T &l, const U & r) { return key_value_pair_view(l) >= key_value_pair_view(r); }
  1010. template<typename T, typename U>
  1011. typename std::enable_if<
  1012. ((std::is_same<T, key_value_pair>::value || std::is_same<T, key_value_pair_view>::value) &&
  1013. std::is_convertible<const U &, key_value_pair_view>::value)
  1014. ||
  1015. ((std::is_same<U, key_value_pair>::value || std::is_same<U, key_value_pair_view>::value) &&
  1016. std::is_convertible<const T & , key_value_pair_view>::value),
  1017. bool>::type
  1018. operator >(const T &l, const U & r) { return key_value_pair_view(l) > key_value_pair_view(r); }
  1019. #else
  1020. bool operator==(const key_value_pair_view &, const key_value_pair_view);
  1021. bool operator!=(const key_value_pair_view &, const key_value_pair_view);
  1022. bool operator<=(const key_value_pair_view &, const key_value_pair_view);
  1023. bool operator< (const key_value_pair_view &, const key_value_pair_view);
  1024. bool operator> (const key_value_pair_view &, const key_value_pair_view);
  1025. bool operator>=(const key_value_pair_view &, const key_value_pair_view);
  1026. #endif
  1027. template<>
  1028. inline key_view key_value_pair::get<0u>() const
  1029. {
  1030. return key();
  1031. }
  1032. template<>
  1033. inline value_view key_value_pair::get<1u>() const
  1034. {
  1035. return value();
  1036. }
  1037. }
  1038. BOOST_PROCESS_V2_END_NAMESPACE
  1039. namespace std
  1040. {
  1041. template<>
  1042. class tuple_size<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair> : integral_constant<std::size_t, 2u> {};
  1043. template<>
  1044. class tuple_element<0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
  1045. {
  1046. public:
  1047. using type = BOOST_PROCESS_V2_NAMESPACE::environment::key_view;
  1048. };
  1049. template<>
  1050. class tuple_element<1u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
  1051. {
  1052. public:
  1053. using type = BOOST_PROCESS_V2_NAMESPACE::environment::value_view;
  1054. };
  1055. template<std::size_t Idx>
  1056. inline auto get(const BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair & kvp)
  1057. -> typename std::tuple_element<Idx, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>::type
  1058. {
  1059. return kvp.get<Idx>();
  1060. }
  1061. template<>
  1062. class tuple_size<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view> : integral_constant<std::size_t, 2u> {};
  1063. template<>
  1064. class tuple_element<0u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>
  1065. {
  1066. public:
  1067. using type = BOOST_PROCESS_V2_NAMESPACE::environment::key_view;
  1068. };
  1069. template<>
  1070. class tuple_element<1u, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>
  1071. {
  1072. public:
  1073. using type = BOOST_PROCESS_V2_NAMESPACE::environment::value_view;
  1074. };
  1075. template<std::size_t Idx>
  1076. inline auto get(BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view kvp)
  1077. -> typename std::tuple_element<Idx, BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>::type
  1078. {
  1079. return kvp.get<Idx>();
  1080. }
  1081. }
  1082. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  1083. namespace environment
  1084. {
  1085. /// A view object for the current environment of this process.
  1086. /**
  1087. * The view might (windows) or might not (posix) be owning;
  1088. * if it owns it will deallocate the on destruction, like a unique_ptr.
  1089. *
  1090. * Note that accessing the environment in this way is not thread-safe.
  1091. *
  1092. * @code
  1093. *
  1094. * void dump_my_env(current_view env = current())
  1095. * {
  1096. * for (auto & [k, v] : env)
  1097. * std::cout << k.string() << " = " << v.string() << std::endl;
  1098. * }
  1099. *
  1100. * @endcode
  1101. *
  1102. *
  1103. */
  1104. struct current_view
  1105. {
  1106. using native_handle_type = environment::native_handle_type;
  1107. using value_type = key_value_pair_view;
  1108. current_view() = default;
  1109. current_view(current_view && nt) = default;
  1110. native_handle_type native_handle() { return handle_.get(); }
  1111. struct iterator
  1112. {
  1113. using value_type = key_value_pair_view;
  1114. using difference_type = int;
  1115. using reference = key_value_pair_view;
  1116. using pointer = key_value_pair_view;
  1117. using iterator_category = std::forward_iterator_tag;
  1118. iterator() = default;
  1119. iterator(const iterator & ) = default;
  1120. iterator(const native_iterator &native_handle) : iterator_(native_handle) {}
  1121. iterator & operator++()
  1122. {
  1123. iterator_ = detail::next(iterator_);
  1124. return *this;
  1125. }
  1126. iterator operator++(int)
  1127. {
  1128. auto last = *this;
  1129. iterator_ = detail::next(iterator_);
  1130. return last;
  1131. }
  1132. key_value_pair_view operator*() const
  1133. {
  1134. return detail::dereference(iterator_);
  1135. }
  1136. friend bool operator==(const iterator & l, const iterator & r) {return l.iterator_ == r.iterator_;}
  1137. friend bool operator!=(const iterator & l, const iterator & r) {return l.iterator_ != r.iterator_;}
  1138. private:
  1139. environment::native_iterator iterator_;
  1140. };
  1141. iterator begin() const {return iterator(handle_.get());}
  1142. iterator end() const {return iterator(detail::find_end(handle_.get()));}
  1143. private:
  1144. std::unique_ptr<typename remove_pointer<native_handle_type>::type,
  1145. detail::native_handle_deleter> handle_{environment::detail::load_native_handle()};
  1146. };
  1147. /// Obtain a handle to the current environment
  1148. inline current_view current() {return current_view();}
  1149. namespace detail
  1150. {
  1151. template<typename Environment>
  1152. auto find_key(Environment & env, key_view ky)
  1153. -> typename std::enable_if<std::is_convertible<decltype(*std::begin(env)), key_value_pair_view>::value, value_view>::type
  1154. {
  1155. const auto itr = std::find_if(std::begin(env), std::end(env),
  1156. [&](key_value_pair_view vp)
  1157. {
  1158. auto tmp = std::get<0>(vp) == ky;
  1159. if (tmp)
  1160. return true;
  1161. else
  1162. return false;
  1163. });
  1164. if (itr != std::end(env))
  1165. return key_value_pair_view(*itr).value();
  1166. else
  1167. return {};
  1168. }
  1169. template<typename Environment>
  1170. auto find_key(Environment & env, key_view ky)
  1171. -> typename std::enable_if<
  1172. !std::is_convertible<decltype(*std::begin(env)), key_value_pair_view>::value &&
  1173. std::is_convertible<decltype(*std::begin(env)), key_value_pair>::value,
  1174. value>::type
  1175. {
  1176. const auto itr = std::find_if(std::begin(env), std::end(env),
  1177. [&](key_value_pair vp)
  1178. {
  1179. auto tmp = std::get<0>(vp) == ky;
  1180. if (tmp)
  1181. return true;
  1182. else
  1183. return false;
  1184. });
  1185. if (itr != std::end(env))
  1186. return key_value_pair(*itr).value();
  1187. else
  1188. return {};
  1189. }
  1190. }
  1191. /// Find the home folder in an environment-like type.
  1192. /**
  1193. * @param env The environment to search. Defaults to the current environment of this process
  1194. *
  1195. * The environment type passed in must be a range with value T that fulfills the following requirements:
  1196. *
  1197. * For `T value`
  1198. *
  1199. * - std::get<0>(value) must return a type comparable to `key_view`.
  1200. * - std::get<1>(value) must return a type convertible to filesystem::path.
  1201. *
  1202. * @return A filesystem::path to the home directory or an empty path if it cannot be found.
  1203. *
  1204. */
  1205. template<typename Environment = current_view>
  1206. inline filesystem::path home(Environment && env = current())
  1207. {
  1208. #if defined(BOOST_PROCESS_V2_WINDOWS)
  1209. return detail::find_key(env, L"HOMEDRIVE").native_string()
  1210. + detail::find_key(env, L"HOMEPATH").native_string();
  1211. #else
  1212. return detail::find_key(env, "HOME").native_string();
  1213. #endif
  1214. }
  1215. /// Find the executable `name` in an environment-like type.
  1216. /**
  1217. * @param env The environment to search. Defaults to the current environment of this process
  1218. *
  1219. * The environment type passed in must be a range with value T that fulfills the following requirements:
  1220. *
  1221. * For `T value`
  1222. *
  1223. * - std::get<0>(value) must return a type comparable to `key_view`.
  1224. * - std::get<1>(value) must return a type convertible to `value_view`.
  1225. *
  1226. *
  1227. * @return A filesystem::path to the executable or an empty path if it cannot be found.
  1228. *
  1229. */
  1230. template<typename Environment = current_view>
  1231. inline BOOST_PROCESS_V2_NAMESPACE::filesystem::path find_executable(
  1232. BOOST_PROCESS_V2_NAMESPACE::filesystem::path name,
  1233. Environment && env = current())
  1234. {
  1235. #if defined(BOOST_PROCESS_V2_WINDOWS)
  1236. auto path = detail::find_key(env, L"PATH");
  1237. auto pathext = detail::find_key(env, L"PATHEXT");
  1238. for (auto pp_view : path)
  1239. {
  1240. // first check if it has the extension already
  1241. BOOST_PROCESS_V2_NAMESPACE::filesystem::path full_nm(name);
  1242. BOOST_PROCESS_V2_NAMESPACE::filesystem::path pp(pp_view.begin(), pp_view.end());
  1243. auto p = pp / full_nm;
  1244. error_code ec;
  1245. if (detail::is_executable(p, ec) && !ec)
  1246. return p;
  1247. for (auto ext : pathext)
  1248. {
  1249. ec.clear();
  1250. BOOST_PROCESS_V2_NAMESPACE::filesystem::path nm(name);
  1251. nm.concat(ext.begin(), ext.end());
  1252. auto p = pp / nm;
  1253. if (detail::is_executable(p, ec) && !ec)
  1254. return p;
  1255. }
  1256. }
  1257. #else
  1258. for (auto pp_view : detail::find_key(env, "PATH"))
  1259. {
  1260. auto p = BOOST_PROCESS_V2_NAMESPACE::filesystem::path(pp_view.begin(), pp_view.end()) / name;
  1261. error_code ec;
  1262. bool is_exec = detail::is_executable(p, ec);
  1263. if (!ec && is_exec)
  1264. return p;
  1265. }
  1266. #endif
  1267. return {};
  1268. }
  1269. /// Get an environment variable from the current process.
  1270. inline value get(const key & k, error_code & ec) { return detail::get(k.c_str(), ec);}
  1271. /// Throwing @overload value get(const key & k, error_code & ec)
  1272. inline value get(const key & k)
  1273. {
  1274. error_code ec;
  1275. auto tmp = detail::get(k.c_str(), ec);
  1276. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::get");
  1277. return tmp;
  1278. }
  1279. /// Disambiguating @overload value get(const key & k, error_code & ec)
  1280. inline value get(basic_cstring_ref<char_type, key_char_traits<char_type>> k, error_code & ec)
  1281. {
  1282. return detail::get(k, ec);
  1283. }
  1284. /// Disambiguating @overload value get(const key & k)
  1285. inline value get(basic_cstring_ref<char_type, key_char_traits<char_type>> k)
  1286. {
  1287. error_code ec;
  1288. auto tmp = detail::get(k, ec);
  1289. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::get");
  1290. return tmp;
  1291. }
  1292. /// Disambiguating @overload value get(const key & k, error_code & ec)
  1293. inline value get(const char_type * c, error_code & ec) { return detail::get(c, ec);}
  1294. /// Disambiguating @overload value get(const key & k)
  1295. inline value get(const char_type * c)
  1296. {
  1297. error_code ec;
  1298. auto tmp = detail::get(c, ec);
  1299. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::get");
  1300. return tmp;
  1301. }
  1302. /// Set an environment variable for the current process.
  1303. inline void set(const key & k, value_view vw, error_code & ec) { detail::set(k, vw, ec);}
  1304. /// Throwing @overload void set(const key & k, value_view vw, error_code & ec)
  1305. inline void set(const key & k, value_view vw)
  1306. {
  1307. error_code ec;
  1308. detail::set(k, vw, ec);
  1309. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
  1310. }
  1311. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1312. 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);}
  1313. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1314. inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, value_view vw)
  1315. {
  1316. error_code ec;
  1317. detail::set(k, vw, ec);
  1318. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
  1319. }
  1320. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1321. inline void set(const char_type * k, value_view vw, error_code & ec) { detail::set(k, vw, ec);}
  1322. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1323. inline void set(const char_type * k, value_view vw)
  1324. {
  1325. error_code ec;
  1326. detail::set(k, vw, ec);
  1327. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
  1328. }
  1329. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1330. template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
  1331. inline void set(const key & k, const Char * vw, error_code & ec)
  1332. {
  1333. value val{vw};
  1334. detail::set(k, val, ec);
  1335. }
  1336. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1337. template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
  1338. inline void set(const key & k, const Char * vw)
  1339. {
  1340. error_code ec;
  1341. value val{vw};
  1342. detail::set(k, val, ec);
  1343. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
  1344. }
  1345. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1346. template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
  1347. inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, const Char * vw, error_code & ec)
  1348. {
  1349. value val{vw};
  1350. detail::set(k, val, ec);
  1351. }
  1352. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1353. template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
  1354. inline void set(basic_cstring_ref<char_type, key_char_traits<char_type>> k, const Char * vw)
  1355. {
  1356. error_code ec;
  1357. value val{vw};
  1358. detail::set(k, val, ec);
  1359. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
  1360. }
  1361. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1362. template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
  1363. inline void set(const char_type * k, const Char * vw, error_code & ec)
  1364. {
  1365. value val{vw};
  1366. detail::set(k, val, ec);
  1367. }
  1368. /// Disambiguating @overload void set(const key & k, value_view vw, error_code & ec)
  1369. template<typename Char, typename = typename std::enable_if<!std::is_same<Char, char_type>::value>::type>
  1370. inline void set(const char_type * k, const Char * vw)
  1371. {
  1372. error_code ec;
  1373. value val{vw};
  1374. detail::set(k, val, ec);
  1375. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::set");
  1376. }
  1377. /// Remove an environment variable from the current process.
  1378. inline void unset(const key & k, error_code & ec) { detail::unset(k, ec);}
  1379. /// Throwing @overload void unset(const key & k, error_code & ec)
  1380. inline void unset(const key & k)
  1381. {
  1382. error_code ec;
  1383. detail::unset(k, ec);
  1384. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::unset");
  1385. }
  1386. /// Disambiguating @overload void unset(const key & k, error_code & ec)
  1387. inline void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> k, error_code & ec)
  1388. {
  1389. detail::unset(k, ec);
  1390. }
  1391. /// Disambiguating @overload void unset(const key & k, error_code & ec)
  1392. inline void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> k)
  1393. {
  1394. error_code ec;
  1395. detail::unset(k, ec);
  1396. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::unset");
  1397. }
  1398. /// Disambiguating @overload void unset(const key & k, error_code & ec)
  1399. inline void unset(const char_type * c, error_code & ec) { detail::unset(c, ec);}
  1400. /// Disambiguating @overload void unset(const key & k, error_code & ec)
  1401. inline void unset(const char_type * c)
  1402. {
  1403. error_code ec;
  1404. detail::unset(c, ec);
  1405. BOOST_PROCESS_V2_NAMESPACE::detail::throw_error(ec, "environment::unset");
  1406. }
  1407. }
  1408. // sub process environment stuff
  1409. #if defined(BOOST_PROCESS_V2_WINDOWS)
  1410. namespace windows { struct default_launcher ;}
  1411. #else
  1412. namespace posix { struct default_launcher ;}
  1413. #endif
  1414. /// Initializer for the environment of sub process.
  1415. /**
  1416. * This will set the environment in a subprocess:
  1417. *
  1418. * @code {.cpp}
  1419. *
  1420. * process proc{executor, find_executable("printenv"), {"foo"}, process_environment{"foo=bar"}};
  1421. * @endcode
  1422. *
  1423. * The environment initializer will persist it's state, so that it can
  1424. * be used multiple times. Do however note the the Operating System is
  1425. * allowed to modify the internal state.
  1426. *
  1427. * @code {.cpp}
  1428. * auto exe = find_executable("printenv");
  1429. * process_environment env = {"FOO=BAR", "BAR=FOO"};
  1430. *
  1431. * process proc1(executor, exe, {"FOO"}, env);
  1432. * process proc2(executor, exe, {"BAR"}, env);
  1433. * @endcode
  1434. *
  1435. *
  1436. */
  1437. struct process_environment
  1438. {
  1439. #if defined(BOOST_PROCESS_V2_WINDOWS)
  1440. template<typename Args>
  1441. static
  1442. std::vector<wchar_t> build_env(Args && args,
  1443. typename std::enable_if<
  1444. std::is_convertible<
  1445. decltype(*std::begin(std::declval<Args>())),
  1446. wcstring_ref>::value>::type * = nullptr)
  1447. {
  1448. std::vector<wchar_t> res;
  1449. std::size_t sz = 1;
  1450. for (wcstring_ref cs : std::forward<Args>(args))
  1451. sz =+ cs.size() + 1;
  1452. res.reserve(sz);
  1453. for (wcstring_ref cs : std::forward<Args>(args))
  1454. res.insert(res.end(), cs.begin(), std::next(cs.end()));
  1455. res.push_back(L'\0');
  1456. return res;
  1457. }
  1458. template<typename Args>
  1459. std::vector<wchar_t> build_env(Args && args,
  1460. typename std::enable_if<
  1461. !std::is_convertible<
  1462. decltype(*std::begin(std::declval<Args>())),
  1463. wcstring_ref>::value>::type * = nullptr)
  1464. {
  1465. for (auto && arg: std::forward<Args>(args))
  1466. env_buffer.emplace_back(arg);
  1467. return build_env(env_buffer);
  1468. }
  1469. process_environment(std::initializer_list<string_view> sv) : unicode_env{build_env(sv)} {}
  1470. process_environment(std::initializer_list<wstring_view> sv) : unicode_env{build_env(sv)} {}
  1471. template<typename Args>
  1472. process_environment(Args && args) : unicode_env{build_env(std::forward<Args>(args))}
  1473. {
  1474. }
  1475. error_code error() {return ec;}
  1476. error_code ec;
  1477. std::vector<environment::key_value_pair> env_buffer;
  1478. std::vector<wchar_t> unicode_env;
  1479. BOOST_PROCESS_V2_DECL
  1480. error_code on_setup(windows::default_launcher & launcher,
  1481. const filesystem::path &, const std::wstring &);
  1482. #else
  1483. template<typename Args>
  1484. static
  1485. std::vector<const char *> build_env(Args && args,
  1486. typename std::enable_if<
  1487. std::is_convertible<
  1488. decltype(*std::begin(std::declval<Args>())),
  1489. cstring_ref>::value>::type * = nullptr)
  1490. {
  1491. std::vector<const char *> env;
  1492. for (auto && e : args)
  1493. env.push_back(e.c_str());
  1494. env.push_back(nullptr);
  1495. return env;
  1496. }
  1497. template<typename Args>
  1498. std::vector<const char *> build_env(Args && args,
  1499. typename std::enable_if<
  1500. !std::is_convertible<
  1501. decltype(*std::begin(std::declval<Args>())),
  1502. cstring_ref>::value>::type * = nullptr)
  1503. {
  1504. std::vector<const char *> env;
  1505. for (auto && arg: std::forward<Args>(args))
  1506. env_buffer.emplace_back(arg);
  1507. for (auto && e : env_buffer)
  1508. env.push_back(e.c_str());
  1509. env.push_back(nullptr);
  1510. return env;
  1511. }
  1512. process_environment(std::initializer_list<string_view> sv) : env{build_env(sv)} { }
  1513. template<typename Args>
  1514. process_environment(Args && args) : env(build_env(std::forward<Args>(args)))
  1515. {
  1516. }
  1517. BOOST_PROCESS_V2_DECL
  1518. error_code on_setup(posix::default_launcher & launcher,
  1519. const filesystem::path &, const char * const *);
  1520. std::vector<environment::key_value_pair> env_buffer;
  1521. std::vector<const char *> env;
  1522. #endif
  1523. };
  1524. BOOST_PROCESS_V2_END_NAMESPACE
  1525. namespace std
  1526. {
  1527. template<>
  1528. struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_view>
  1529. {
  1530. std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_view kv) const noexcept
  1531. {
  1532. return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
  1533. }
  1534. };
  1535. template<>
  1536. struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::value_view>
  1537. {
  1538. std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::value_view kv) const noexcept
  1539. {
  1540. return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
  1541. }
  1542. };
  1543. template<>
  1544. struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view>
  1545. {
  1546. std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view kv) const noexcept
  1547. {
  1548. return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
  1549. }
  1550. };
  1551. template<>
  1552. struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key>
  1553. {
  1554. std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_view kv) const noexcept
  1555. {
  1556. return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
  1557. }
  1558. };
  1559. template<>
  1560. struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::value>
  1561. {
  1562. std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::value_view kv) const noexcept
  1563. {
  1564. return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
  1565. }
  1566. };
  1567. template<>
  1568. struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
  1569. {
  1570. std::size_t operator()( BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair_view kv) const noexcept
  1571. {
  1572. return BOOST_PROCESS_V2_NAMESPACE::environment::hash_value(kv);
  1573. }
  1574. };
  1575. }
  1576. #if defined(BOOST_PROCESS_V2_HEADER_ONLY)
  1577. #include <boost/process/v2/impl/environment.ipp>
  1578. #include <boost/process/v2/detail/impl/environment.ipp>
  1579. #endif
  1580. #endif //BOOST_PROCESS_V2_ENVIRONMENT_HPP