You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
705 lines
24 KiB
705 lines
24 KiB
// Copyright (c) 2016 Klemens D. Morgenstern |
|
// |
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying |
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
|
|
#ifndef BOOST_PROCESS_ENVIRONMENT_HPP_ |
|
#define BOOST_PROCESS_ENVIRONMENT_HPP_ |
|
|
|
#include <boost/process/detail/config.hpp> |
|
#include <boost/algorithm/string/split.hpp> |
|
#include <boost/algorithm/string/case_conv.hpp> |
|
#include <boost/iterator/transform_iterator.hpp> |
|
#include <boost/filesystem/path.hpp> |
|
|
|
#if defined(BOOST_POSIX_API) |
|
#include <boost/process/detail/posix/environment.hpp> |
|
#elif defined(BOOST_WINDOWS_API) |
|
#include <boost/process/detail/windows/environment.hpp> |
|
#endif |
|
|
|
namespace boost { namespace process { |
|
|
|
namespace detail { |
|
|
|
template<typename Char, typename Environment> |
|
struct const_entry |
|
{ |
|
using value_type = Char ; |
|
using pointer = const value_type * ; |
|
using string_type = std::basic_string<value_type> ; |
|
using range = boost::iterator_range<pointer> ; |
|
using environment_t = Environment ; |
|
|
|
std::vector<string_type> to_vector() const |
|
{ |
|
if (_data == nullptr) |
|
return std::vector<string_type>(); |
|
std::vector<string_type> data; |
|
auto str = string_type(_data); |
|
struct splitter |
|
{ |
|
bool operator()(wchar_t w) const {return w == api::env_seperator<wchar_t>();} |
|
bool operator()(char c) const {return c == api::env_seperator<char> ();} |
|
} s; |
|
boost::split(data, _data, s); |
|
return std::move(data); |
|
} |
|
string_type to_string() const |
|
{ |
|
if (_data != nullptr) |
|
return string_type(_data); |
|
else |
|
return string_type(); |
|
} |
|
string_type get_name() const {return string_type(_name.begin(), _name.end());} |
|
explicit const_entry(string_type&& name, pointer data, environment_t & env_) : |
|
_name(std::move(name)), _data(data), _env(&env_) {} |
|
|
|
explicit const_entry(string_type &&name, environment_t & env) : |
|
_name(std::move(name)), _data(nullptr), _env(&env) {} |
|
const_entry(const const_entry&) = default; |
|
const_entry& operator=(const const_entry&) = default; |
|
|
|
void reload() |
|
{ |
|
auto p = _env->find(_name); |
|
if (p == _env->end()) |
|
_data = nullptr; |
|
else |
|
_data = p->_data; |
|
this->_env->reload(); |
|
|
|
} |
|
bool empty() const |
|
{ |
|
return _data == nullptr; |
|
} |
|
protected: |
|
string_type _name; |
|
pointer _data; |
|
environment_t * _env; |
|
}; |
|
|
|
template<typename Char, typename Environment> |
|
struct entry : const_entry<Char, Environment> |
|
{ |
|
using father = const_entry<Char, Environment>; |
|
using value_type = typename father::value_type; |
|
using string_type = typename father::string_type; |
|
using pointer = typename father::pointer; |
|
using environment_t = typename father::environment_t; |
|
|
|
explicit entry(string_type&& name, pointer data, environment_t & env) : |
|
father(std::move(name), data, env) {} |
|
|
|
explicit entry(string_type &&name, environment_t & env_) : |
|
father(std::move(name), env_) {} |
|
|
|
entry(const entry&) = default; |
|
entry& operator=(const entry&) = default; |
|
|
|
void assign(const string_type &value) |
|
{ |
|
this->_env->set(this->_name, value); |
|
this->reload(); |
|
} |
|
void assign(const std::vector<string_type> &value) |
|
{ |
|
string_type data; |
|
for (auto &v : value) |
|
{ |
|
if (&v != &value.front()) |
|
data += api::env_seperator<value_type>(); |
|
data += v; |
|
} |
|
this->_env->set(this->_name, data); |
|
this->reload(); |
|
|
|
} |
|
void assign(const std::initializer_list<string_type> &value) |
|
{ |
|
string_type data; |
|
for (auto &v : value) |
|
{ |
|
if (&v != &*value.begin()) |
|
data += api::env_seperator<value_type>(); |
|
data += v; |
|
} |
|
this->_env->set(this->_name, data); |
|
this->reload(); |
|
|
|
} |
|
void append(const string_type &value) |
|
{ |
|
if (this->_data == nullptr) |
|
this->_env->set(this->_name, value); |
|
else |
|
{ |
|
string_type st = this->_data; |
|
this->_env->set(this->_name, st + api::env_seperator<value_type>() + value); |
|
} |
|
|
|
|
|
this->reload(); |
|
|
|
} |
|
void clear() |
|
{ |
|
this->_env->reset(this->_name); |
|
this->_env->reload(); |
|
this->_data = nullptr; |
|
} |
|
entry &operator=(const string_type & value) |
|
{ |
|
assign(value); |
|
return *this; |
|
} |
|
entry &operator=(const std::vector<string_type> & value) |
|
{ |
|
assign(value); |
|
return *this; |
|
} |
|
entry &operator=(const std::initializer_list<string_type> & value) |
|
{ |
|
assign(value); |
|
return *this; |
|
} |
|
entry &operator+=(const string_type & value) |
|
{ |
|
append(value); |
|
return *this; |
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename Char, typename Environment> |
|
struct make_entry |
|
{ |
|
|
|
make_entry(const make_entry&) = default; |
|
make_entry& operator=(const make_entry&) = default; |
|
|
|
Environment *env; |
|
make_entry(Environment & env) : env(&env) {}; |
|
entry<Char, Environment> operator()(const Char* data) const |
|
{ |
|
auto p = data; |
|
while ((*p != equal_sign<Char>()) && (*p != null_char<Char>())) |
|
p++; |
|
auto name = std::basic_string<Char>(data, p); |
|
p++; //go behind equal sign |
|
|
|
return entry<Char, Environment>(std::move(name), p, *env); |
|
} |
|
}; |
|
|
|
template<typename Char, typename Environment> |
|
struct make_const_entry |
|
{ |
|
|
|
make_const_entry(const make_const_entry&) = default; |
|
make_const_entry& operator=(const make_const_entry&) = default; |
|
|
|
Environment *env; |
|
make_const_entry(Environment & env) : env(&env) {}; |
|
const_entry<Char, Environment> operator()(const Char* data) const |
|
{ |
|
auto p = data; |
|
while ((*p != equal_sign<Char>()) && (*p != null_char<Char>())) |
|
p++; |
|
auto name = std::basic_string<Char>(data, p); |
|
p++; //go behind equal sign |
|
|
|
return const_entry<Char, Environment>(std::move(name), p, *env); |
|
} |
|
}; |
|
|
|
} |
|
|
|
#if !defined (BOOST_PROCESS_DOXYGEN) |
|
|
|
template<typename Char, template <class> class Implementation = detail::api::basic_environment_impl> |
|
class basic_environment_impl : public Implementation<Char> |
|
{ |
|
Char** _get_end() const |
|
{ |
|
auto p = this->_env_impl; |
|
while (*p != nullptr) |
|
p++; |
|
|
|
return p; |
|
} |
|
public: |
|
using string_type = std::basic_string<Char>; |
|
using implementation_type = Implementation<Char>; |
|
using base_type = basic_environment_impl<Char, Implementation>; |
|
using entry_maker = detail::make_entry<Char, base_type>; |
|
using entry_type = detail::entry <Char, base_type>; |
|
using const_entry_type = detail::const_entry <Char, const base_type>; |
|
using const_entry_maker = detail::make_const_entry<Char, const base_type>; |
|
|
|
friend entry_type; |
|
friend const_entry_type; |
|
|
|
using iterator = boost::transform_iterator< entry_maker, Char**, entry_type, entry_type>; |
|
using const_iterator = boost::transform_iterator<const_entry_maker, Char**, const_entry_type, const_entry_type>; |
|
using size_type = std::size_t; |
|
|
|
iterator begin() {return iterator(this->_env_impl, entry_maker(*this));} |
|
const_iterator begin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));} |
|
const_iterator cbegin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));} |
|
|
|
iterator end() {return iterator(_get_end(), entry_maker(*this));} |
|
const_iterator end() const {return const_iterator(_get_end(), const_entry_maker(*this));} |
|
const_iterator cend() const {return const_iterator(_get_end(), const_entry_maker(*this));} |
|
|
|
iterator find( const string_type& key ) |
|
{ |
|
auto p = this->_env_impl; |
|
auto st1 = key + ::boost::process::detail::equal_sign<Char>(); |
|
while (*p != nullptr) |
|
{ |
|
if (std::equal(st1.begin(), st1.end(), *p)) |
|
break; |
|
p++; |
|
} |
|
return iterator(p, entry_maker(*this)); |
|
} |
|
const_iterator find( const string_type& key ) const |
|
{ |
|
auto p = this->_env_impl; |
|
auto st1 = key + ::boost::process::detail::equal_sign<Char>(); |
|
while (*p != nullptr) |
|
{ |
|
if (std::equal(st1.begin(), st1.end(), *p)) |
|
break; |
|
p++; |
|
} |
|
return const_iterator(p, const_entry_maker(*this)); |
|
} |
|
|
|
std::size_t count(const string_type & st) const |
|
{ |
|
auto p = this->_env_impl; |
|
auto st1 = st + ::boost::process::detail::equal_sign<Char>(); |
|
while (*p != nullptr) |
|
{ |
|
if (std::equal(st1.begin(), st1.end(), *p)) |
|
return 1u; |
|
p++; |
|
} |
|
return 0u; |
|
} |
|
void erase(const string_type & id) |
|
{ |
|
implementation_type::reset(id); |
|
this->reload(); |
|
} |
|
std::pair<iterator,bool> emplace(const string_type & id, const string_type & value) |
|
{ |
|
auto f = find(id); |
|
if (f == end()) |
|
{ |
|
implementation_type::set(id, value); |
|
this->reload(); |
|
return std::pair<iterator, bool>(find(id), true); |
|
} |
|
else |
|
return std::pair<iterator, bool>(f, false); |
|
} |
|
using implementation_type::implementation_type; |
|
using implementation_type::operator=; |
|
using native_handle_type = typename implementation_type::native_handle_type; |
|
using implementation_type::native_handle; |
|
//copy ctor if impl is copy-constructible |
|
bool empty() |
|
{ |
|
return *this->_env_impl == nullptr; |
|
} |
|
std::size_t size() const |
|
{ |
|
return (_get_end() - this->_env_impl); |
|
} |
|
void clear() |
|
{ |
|
std::vector<string_type> names; |
|
names.resize(size()); |
|
std::transform(cbegin(), cend(), names.begin(), [](const const_entry_type & cet){return cet.get_name();}); |
|
|
|
for (auto & nm : names) |
|
implementation_type::reset(nm); |
|
|
|
this->reload(); |
|
} |
|
|
|
entry_type at( const string_type& key ) |
|
{ |
|
auto f = find(key); |
|
if (f== end()) |
|
throw std::out_of_range(key + " not found"); |
|
return *f; |
|
} |
|
const_entry_type at( const string_type& key ) const |
|
{ |
|
auto f = find(key); |
|
if (f== end()) |
|
throw std::out_of_range(key + " not found"); |
|
return *f; |
|
} |
|
entry_type operator[](const string_type & key) |
|
{ |
|
auto p = find(key); |
|
if (p != end()) |
|
return *p; |
|
|
|
return entry_type(string_type(key), *this); |
|
} |
|
}; |
|
#endif |
|
|
|
#if defined(BOOST_PROCESS_DOXYGEN) |
|
/**Template representation of environments. It takes a character type (`char` or `wchar_t`) |
|
* as template parameter to implement the environment |
|
*/ |
|
template<typename Char> |
|
class basic_environment |
|
{ |
|
|
|
public: |
|
typedef std::basic_string<Char> string_type; |
|
typedef boost::transform_iterator< entry_maker, Char**> iterator ; |
|
typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ; |
|
typedef std::size_t size_type ; |
|
|
|
iterator begin() ; ///<Returns an iterator to the beginning |
|
const_iterator begin() const ; ///<Returns an iterator to the beginning |
|
const_iterator cbegin() const ; ///<Returns an iterator to the beginning |
|
|
|
iterator end() ; ///<Returns an iterator to the end |
|
const_iterator end() const; ///<Returns an iterator to the end |
|
const_iterator cend() const; ///<Returns an iterator to the end |
|
|
|
iterator find( const string_type& key ); ///<Find a variable by its name |
|
const_iterator find( const string_type& key ) const; ///<Find a variable by its name |
|
|
|
std::size_t count(const string_type & st) const; ///<Number of variables |
|
void erase(const string_type & id); ///<Erase variable by id. |
|
///Emplace an environment variable. |
|
std::pair<iterator,bool> emplace(const string_type & id, const string_type & value); |
|
|
|
///Default constructor |
|
basic_environment(); |
|
///Copy constructor. |
|
basic_environment(const basic_environment & ); |
|
///Move constructor. |
|
basic_environment(basic_environment && ); |
|
|
|
///Copy assignment. |
|
basic_environment& operator=(const basic_environment & ); |
|
///Move assignment. |
|
basic_environment& operator=(basic_environment && ); |
|
|
|
typedef typename detail::implementation_type::native_handle_type native_handle; |
|
|
|
///Check if environment has entries. |
|
bool empty(); |
|
///Get the number of variables. |
|
std::size_t size() const; |
|
///Clear the environment. @attention Use with care, passed environment cannot be empty. |
|
void clear(); |
|
///Get the entry with the key. Throws if it does not exist. |
|
entry_type at( const string_type& key ); |
|
///Get the entry with the key. Throws if it does not exist. |
|
const_entry_type at( const string_type& key ) const; |
|
///Get the entry with the given key. It creates the entry if it doesn't exist. |
|
entry_type operator[](const string_type & key); |
|
|
|
/**Proxy class used for read access to members by [] or .at() |
|
* @attention Holds a reference to the environment it was created from. |
|
*/ |
|
template<typename Char, typename Environment> |
|
struct const_entry_type |
|
{ |
|
typedef Char value_type; |
|
typedef const value_type * pointer; |
|
typedef std::basic_string<value_type> string_type; |
|
typedef boost::iterator_range<pointer> range; |
|
typedef Environment environment_t; |
|
|
|
///Split the entry by ";" or ":" and return it as a vector. Used by PATH. |
|
std::vector<string_type> to_vector() const |
|
///Get the value as string. |
|
string_type to_string() const |
|
///Get the name of this entry. |
|
string_type get_name() const {return string_type(_name.begin(), _name.end());} |
|
///Copy Constructor |
|
const_entry(const const_entry&) = default; |
|
///Move Constructor |
|
const_entry& operator=(const const_entry&) = default; |
|
///Check if the entry is empty. |
|
bool empty() const; |
|
}; |
|
|
|
/**Proxy class used for read and write access to members by [] or .at() |
|
* @attention Holds a reference to the environment it was created from. |
|
*/ |
|
template<typename Char, typename Environment> |
|
struct entry_type |
|
{ |
|
|
|
typedef Char value_type; |
|
typedef const value_type * pointer; |
|
typedef std::basic_string<value_type> string_type; |
|
typedef boost::iterator_range<pointer> range; |
|
typedef Environment environment_t; |
|
|
|
///Split the entry by ";" or ":" and return it as a vector. Used by PATH. |
|
std::vector<string_type> to_vector() const |
|
///Get the value as string. |
|
string_type to_string() const |
|
///Get the name of this entry. |
|
string_type get_name() const {return string_type(_name.begin(), _name.end());} |
|
///Copy Constructor |
|
entry(const entry&) = default; |
|
///Move Constructor |
|
entry& operator=(const entry&) = default; |
|
///Check if the entry is empty. |
|
bool empty() const; |
|
|
|
///Assign a string to the value |
|
void assign(const string_type &value); |
|
///Assign a set of strings to the entry; they will be separated by ';' or ':'. |
|
void assign(const std::vector<string_type> &value); |
|
///Append a string to the end of the entry, it will separated by ';' or ':'. |
|
void append(const string_type &value); |
|
///Reset the value |
|
void clear(); |
|
///Assign a string to the entry. |
|
entry &operator=(const string_type & value); |
|
///Assign a set of strings to the entry; they will be separated by ';' or ':'. |
|
entry &operator=(const std::vector<string_type> & value); |
|
///Append a string to the end of the entry, it will separated by ';' or ':'. |
|
entry &operator+=(const string_type & value); |
|
}; |
|
|
|
}; |
|
|
|
/**Template representation of the environment of this process. It takes a template |
|
* as template parameter to implement the environment. All instances of this class |
|
* refer to the same environment, but might not get updated if another one makes changes. |
|
*/ |
|
template<typename Char> |
|
class basic_native_environment |
|
{ |
|
|
|
public: |
|
typedef std::basic_string<Char> string_type; |
|
typedef boost::transform_iterator< entry_maker, Char**> iterator ; |
|
typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ; |
|
typedef std::size_t size_type ; |
|
|
|
iterator begin() ; ///<Returns an iterator to the beginning |
|
const_iterator begin() const ; ///<Returns an iterator to the beginning |
|
const_iterator cbegin() const ; ///<Returns an iterator to the beginning |
|
|
|
iterator end() ; ///<Returns an iterator to the end |
|
const_iterator end() const; ///<Returns an iterator to the end |
|
const_iterator cend() const; ///<Returns an iterator to the end |
|
|
|
iterator find( const string_type& key ); ///<Find a variable by its name |
|
const_iterator find( const string_type& key ) const; ///<Find a variable by its name |
|
|
|
std::size_t count(const string_type & st) const; ///<Number of variables |
|
void erase(const string_type & id); ///<Erase variable by id. |
|
///Emplace an environment variable. |
|
std::pair<iterator,bool> emplace(const string_type & id, const string_type & value); |
|
|
|
///Default constructor |
|
basic_native_environment(); |
|
///Move constructor. |
|
basic_native_environment(basic_native_environment && ); |
|
///Move assignment. |
|
basic_native_environment& operator=(basic_native_environment && ); |
|
|
|
typedef typename detail::implementation_type::native_handle_type native_handle; |
|
|
|
///Check if environment has entries. |
|
bool empty(); |
|
///Get the number of variables. |
|
std::size_t size() const; |
|
///Get the entry with the key. Throws if it does not exist. |
|
entry_type at( const string_type& key ); |
|
///Get the entry with the key. Throws if it does not exist. |
|
const_entry_type at( const string_type& key ) const; |
|
///Get the entry with the given key. It creates the entry if it doesn't exist. |
|
entry_type operator[](const string_type & key); |
|
|
|
/**Proxy class used for read access to members by [] or .at() |
|
* @attention Holds a reference to the environment it was created from. |
|
*/ |
|
template<typename Char, typename Environment> |
|
struct const_entry_type |
|
{ |
|
typedef Char value_type; |
|
typedef const value_type * pointer; |
|
typedef std::basic_string<value_type> string_type; |
|
typedef boost::iterator_range<pointer> range; |
|
typedef Environment environment_t; |
|
|
|
///Split the entry by ";" or ":" and return it as a vector. Used by PATH. |
|
std::vector<string_type> to_vector() const |
|
///Get the value as string. |
|
string_type to_string() const |
|
///Get the name of this entry. |
|
string_type get_name() const {return string_type(_name.begin(), _name.end());} |
|
///Copy Constructor |
|
const_entry(const const_entry&) = default; |
|
///Move Constructor |
|
const_entry& operator=(const const_entry&) = default; |
|
///Check if the entry is empty. |
|
bool empty() const; |
|
}; |
|
|
|
/**Proxy class used for read and write access to members by [] or .at() |
|
* @attention Holds a reference to the environment it was created from. |
|
*/ |
|
template<typename Char, typename Environment> |
|
struct entry_type |
|
{ |
|
|
|
typedef Char value_type; |
|
typedef const value_type * pointer; |
|
typedef std::basic_string<value_type> string_type; |
|
typedef boost::iterator_range<pointer> range; |
|
typedef Environment environment_t; |
|
|
|
///Split the entry by ";" or ":" and return it as a vector. Used by PATH. |
|
std::vector<string_type> to_vector() const |
|
///Get the value as string. |
|
string_type to_string() const |
|
///Get the name of this entry. |
|
string_type get_name() const {return string_type(_name.begin(), _name.end());} |
|
///Copy Constructor |
|
entry(const entry&) = default; |
|
///Move Constructor |
|
entry& operator=(const entry&) = default; |
|
///Check if the entry is empty. |
|
bool empty() const; |
|
|
|
///Assign a string to the value |
|
void assign(const string_type &value); |
|
///Assign a set of strings to the entry; they will be separated by ';' or ':'. |
|
void assign(const std::vector<string_type> &value); |
|
///Append a string to the end of the entry, it will separated by ';' or ':'. |
|
void append(const string_type &value); |
|
///Reset the value |
|
void clear(); |
|
///Assign a string to the entry. |
|
entry &operator=(const string_type & value); |
|
///Assign a set of strings to the entry; they will be separated by ';' or ':'. |
|
entry &operator=(const std::vector<string_type> & value); |
|
///Append a string to the end of the entry, it will separated by ';' or ':'. |
|
entry &operator+=(const string_type & value); |
|
}; |
|
|
|
}; |
|
|
|
#endif |
|
|
|
///Definition of the environment for the current process. |
|
template<typename Char> |
|
class basic_native_environment : public basic_environment_impl<Char, detail::api::native_environment_impl> |
|
{ |
|
public: |
|
using base_type = basic_environment_impl<Char, detail::api::native_environment_impl>; |
|
using base_type::base_type; |
|
using base_type::operator=; |
|
}; |
|
|
|
///Type definition to hold a seperate environment. |
|
template<typename Char> |
|
class basic_environment : public basic_environment_impl<Char, detail::api::basic_environment_impl> |
|
{ |
|
public: |
|
using base_type = basic_environment_impl<Char, detail::api::basic_environment_impl>; |
|
using base_type::base_type; |
|
using base_type::operator=; |
|
}; |
|
|
|
|
|
#if !defined(BOOST_NO_ANSI_APIS) |
|
///Definition of the environment for the current process. |
|
typedef basic_native_environment<char> native_environment; |
|
#endif |
|
///Definition of the environment for the current process. |
|
typedef basic_native_environment<wchar_t> wnative_environment; |
|
|
|
#if !defined(BOOST_NO_ANSI_APIS) |
|
///Type definition to hold a seperate environment. |
|
typedef basic_environment<char> environment; |
|
#endif |
|
///Type definition to hold a seperate environment. |
|
typedef basic_environment<wchar_t> wenvironment; |
|
|
|
} |
|
|
|
///Namespace containing information of the calling process. |
|
namespace this_process |
|
{ |
|
|
|
///Definition of the native handle type. |
|
typedef ::boost::process::detail::api::native_handle_t native_handle_type; |
|
|
|
#if !defined(BOOST_NO_ANSI_APIS) |
|
///Definition of the environment for this process. |
|
using ::boost::process::native_environment; |
|
#endif |
|
///Definition of the environment for this process. |
|
using ::boost::process::wnative_environment; |
|
|
|
///Get the process id of the current process. |
|
inline int get_id() { return ::boost::process::detail::api::get_id();} |
|
///Get the native handle of the current process. |
|
inline native_handle_type native_handle() { return ::boost::process::detail::api::native_handle();} |
|
#if !defined(BOOST_NO_ANSI_APIS) |
|
///Get the enviroment of the current process. |
|
inline native_environment environment() { return ::boost::process:: native_environment(); } |
|
#endif |
|
///Get the enviroment of the current process. |
|
inline wnative_environment wenvironment() { return ::boost::process::wnative_environment(); } |
|
///Get the path environment variable of the current process runs. |
|
inline std::vector<boost::filesystem::path> path() |
|
{ |
|
#if defined(BOOST_WINDOWS_API) |
|
const ::boost::process::wnative_environment ne{}; |
|
typedef typename ::boost::process::wnative_environment::const_entry_type value_type; |
|
const auto id = L"PATH"; |
|
#else |
|
const ::boost::process::native_environment ne{}; |
|
typedef typename ::boost::process::native_environment::const_entry_type value_type; |
|
const auto id = "PATH"; |
|
#endif |
|
|
|
auto itr = std::find_if(ne.cbegin(), ne.cend(), |
|
[&](const value_type & e) |
|
{return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());}); |
|
|
|
if (itr == ne.cend()) |
|
return {}; |
|
|
|
auto vec = itr->to_vector(); |
|
|
|
std::vector<boost::filesystem::path> val; |
|
val.resize(vec.size()); |
|
|
|
std::copy(vec.begin(), vec.end(), val.begin()); |
|
|
|
return val; |
|
} |
|
} |
|
} |
|
#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENVIRONMENT_HPP_ */
|
|
|