environment.hpp 65 KB

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