123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- // 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 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;
- static constexpr auto id = L"PATH";
- #else
- const ::boost::process::native_environment ne{};
- typedef typename ::boost::process::native_environment::const_entry_type value_type;
- static constexpr 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_ */
|