diff options
Diffstat (limited to 'boost/process/environment.hpp')
-rw-r--r-- | boost/process/environment.hpp | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/boost/process/environment.hpp b/boost/process/environment.hpp new file mode 100644 index 0000000000..1684798b87 --- /dev/null +++ b/boost/process/environment.hpp @@ -0,0 +1,698 @@ +// 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 seperated by ';' or ':'. + void assign(const std::vector<string_type> &value); + ///Append a string to the end of the entry, it will seperated 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 seperated by ';' or ':'. + entry &operator=(const std::vector<string_type> & value); + ///Append a string to the end of the entry, it will seperated 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 seperated by ';' or ':'. + void assign(const std::vector<string_type> &value); + ///Append a string to the end of the entry, it will seperated 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 seperated by ';' or ':'. + entry &operator=(const std::vector<string_type> & value); + ///Append a string to the end of the entry, it will seperated 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=; +}; + + + +///Definition of the environment for the current process. +typedef basic_native_environment<char> native_environment; +///Definition of the environment for the current process. +typedef basic_native_environment<wchar_t> wnative_environment; + +///Type definition to hold a seperate environment. +typedef basic_environment<char> environment; +///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; + +///Definition of the environment for this process. +using ::boost::process::native_environment; +///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();} +///Get the enviroment of the current process. +inline native_environment environment() { return ::boost::process:: native_environment(); } +///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_ */ |