environment.hpp 65 KB

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