diff options
Diffstat (limited to 'boost/process/detail/windows/environment.hpp')
-rw-r--r-- | boost/process/detail/windows/environment.hpp | 650 |
1 files changed, 324 insertions, 326 deletions
diff --git a/boost/process/detail/windows/environment.hpp b/boost/process/detail/windows/environment.hpp index b73da1bd42..13aa587da8 100644 --- a/boost/process/detail/windows/environment.hpp +++ b/boost/process/detail/windows/environment.hpp @@ -1,356 +1,354 @@ -// 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_DETAIL_WINDOWS_ENV_STORAGE_HPP_
-#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
- -#include <string>
-#include <vector>
-#include <unordered_map>
-#include <boost/detail/winapi/error_codes.hpp>
-#include <boost/detail/winapi/environment.hpp>
-#include <boost/process/detail/config.hpp>
-#include <boost/detail/winapi/get_current_process.hpp>
-#include <boost/detail/winapi/get_current_process_id.hpp>
-#include <algorithm>
-#include <boost/process/locale.hpp>
- -namespace boost { namespace process { namespace detail { namespace windows {
- -template<typename Char>
-class native_environment_impl
-{
- static void _deleter(Char* p) {boost::detail::winapi::free_environment_strings(p);};
- std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::detail::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter};
- static inline std::vector<Char*> _load_var(Char* p);
- std::vector<Char*> _env_arr{_load_var(_buf.get())};
-public:
- using char_type = Char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = pointer_type;
- void reload()
- {
- _buf.reset(boost::detail::winapi::get_environment_strings<Char>());
- _env_arr = _load_var(_buf.get());
- _env_impl = &*_env_arr.begin();
- }
- - string_type get(const pointer_type id);
- void set(const pointer_type id, const pointer_type value);
- void reset(const pointer_type id);
- - string_type get(const string_type & id) {return get(id.c_str());}
- void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
- void reset(const string_type & id) {reset(id.c_str());}
- - native_environment_impl() = default;
- native_environment_impl(const native_environment_impl& ) = delete;
- native_environment_impl(native_environment_impl && ) = default;
- native_environment_impl & operator=(const native_environment_impl& ) = delete;
- native_environment_impl & operator=(native_environment_impl && ) = default;
- Char ** _env_impl = &*_env_arr.begin();
- - native_handle_type native_handle() const {return _buf.get();}
-};
- -template<typename Char>
-inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_type
-{
- Char buf[4096];
- auto size = boost::detail::winapi::get_environment_variable(id, buf, sizeof(buf));
- if (size == 0) //failed
- {
- auto err = ::boost::detail::winapi::GetLastError();
- if (err == ::boost::detail::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value
- return "";
- else
- throw process_error(std::error_code(err, std::system_category()),
- "GetEnvironmentVariable() failed");
- }
- - if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong
- {
- /*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
- * but I used 32768 so it is a multiple of 4096.
- */
- constexpr static std::size_t max_size = 32768;
- //Handle variables longer then buf.
- std::size_t buf_size = sizeof(buf);
- while (buf_size <= max_size)
- {
- std::vector<Char> buf(buf_size);
- auto size = boost::detail::winapi::get_environment_variable(id, buf.data(), buf.size());
- - if (size == buf_size) //buffer to small
- buf_size *= 2;
- else if (size == 0)
- ::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed");
- else
- return std::basic_string<Char>(
- buf.data(), buf.data()+ size + 1);
- - }
- - }
- return std::basic_string<Char>(buf, buf+size+1);
-}
- -template<typename Char>
-inline void native_environment_impl<Char>::set(const pointer_type id, const pointer_type value)
-{
- boost::detail::winapi::set_environment_variable(id, value);
-}
- -template<typename Char>
-inline void native_environment_impl<Char>::reset(const pointer_type id)
-{
- boost::detail::winapi::set_environment_variable(id, nullptr);
-}
- -template<typename Char>
-std::vector<Char*> native_environment_impl<Char>::_load_var(Char* p)
-{
- std::vector<Char*> ret;
- if (*p != null_char<Char>())
- {
- ret.push_back(p);
- while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
- {
- if (*p==null_char<Char>())
- {
- p++;
- ret.push_back(p);
- }
- else
- p++;
- }
- }
- p++;
- ret.push_back(nullptr);
- - return ret;
-}
- - -template<typename Char>
-struct basic_environment_impl
-{
- std::vector<Char> _data = {null_char<Char>()};
- static std::vector<Char*> _load_var(Char* p);
- std::vector<Char*> _env_arr{_load_var(_data.data())};
-public:
- using char_type = Char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = pointer_type;
- - std::size_t size() const { return _data.size();}
- - void reload()
- {
- _env_arr = _load_var(_data.data());
- _env_impl = _env_arr.data();
- }
- - string_type get(const pointer_type id) {return get(string_type(id));}
- void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
- void reset(const pointer_type id) {reset(string_type(id));}
- - string_type get(const string_type & id);
- void set(const string_type & id, const string_type & value);
- void reset(const string_type & id);
- - inline basic_environment_impl(const native_environment_impl<Char> & nei);
- basic_environment_impl() = default;
- basic_environment_impl(const basic_environment_impl& rhs)
- : _data(rhs._data)
- {
- }
- basic_environment_impl(basic_environment_impl && rhs)
- : _data(std::move(rhs._data)),
- _env_arr(std::move(rhs._env_arr)),
- _env_impl(_env_arr.data())
- {
- }
- basic_environment_impl &operator=(basic_environment_impl && rhs)
- {
- _data = std::move(rhs._data);
- //reload();
- _env_arr = std::move(rhs._env_arr);
- _env_impl = _env_arr.data();
- - return *this;
- }
- basic_environment_impl & operator=(const basic_environment_impl& rhs)
- {
- _data = rhs._data;
- reload();
- return *this;
- }
- - template<typename CharR>
- explicit inline basic_environment_impl(
- const basic_environment_impl<CharR>& rhs,
- const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
- : _data(::boost::process::detail::convert(rhs._data, cv))
- {
- }
- - template<typename CharR>
- basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
- {
- _data = ::boost::process::detail::convert(rhs._data);
- _env_arr = _load_var(&*_data.begin());
- _env_impl = &*_env_arr.begin();
- return *this;
- }
- - Char ** _env_impl = &*_env_arr.begin();
- - native_handle_type native_handle() const {return &*_data.begin();}
-};
- - -template<typename Char>
-basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
-{
- auto beg = nei.native_handle();
- auto p = beg;
- while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
- p++;
- p++; //pointing to the second nullchar
- p++; //to get the pointer behing the second nullchar, so it's end.
- - this->_data.assign(beg, p);
- this->reload();
-}
- - -template<typename Char>
-inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
-{
- - if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
- return string_type(_data.data()); //null-char is handled by the string.
- - std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
- seq.insert(seq.end(), id.begin(), id.end());
- seq.push_back('=');
- - auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
- - if (itr == _data.end()) //not found
- return "";
- - itr += seq.size(); //advance to the value behind the '='; the std::string will take care of finding the null-char.
- - return string_type(&*itr);
-}
- -template<typename Char>
-inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
-{
- reset(id);
+// 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_DETAIL_WINDOWS_ENV_STORAGE_HPP_ +#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ + +#include <string> +#include <vector> +#include <unordered_map> +#include <boost/winapi/error_codes.hpp> +#include <boost/winapi/environment.hpp> +#include <boost/winapi/get_current_process.hpp> +#include <boost/winapi/get_current_process_id.hpp> +#include <boost/process/detail/config.hpp> +#include <algorithm> +#include <boost/process/locale.hpp> + +namespace boost { namespace process { namespace detail { namespace windows { + +template<typename Char> +class native_environment_impl +{ + static void _deleter(Char* p) {boost::winapi::free_environment_strings(p);}; + std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter}; + static inline std::vector<Char*> _load_var(Char* p); + std::vector<Char*> _env_arr{_load_var(_buf.get())}; +public: + using char_type = Char; + using pointer_type = const char_type*; + using string_type = std::basic_string<char_type>; + using native_handle_type = pointer_type; + void reload() + { + _buf.reset(boost::winapi::get_environment_strings<Char>()); + _env_arr = _load_var(_buf.get()); + _env_impl = &*_env_arr.begin(); + } + + string_type get(const pointer_type id); + void set(const pointer_type id, const pointer_type value); + void reset(const pointer_type id); + + string_type get(const string_type & id) {return get(id.c_str());} + void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); } + void reset(const string_type & id) {reset(id.c_str());} + + native_environment_impl() = default; + native_environment_impl(const native_environment_impl& ) = delete; + native_environment_impl(native_environment_impl && ) = default; + native_environment_impl & operator=(const native_environment_impl& ) = delete; + native_environment_impl & operator=(native_environment_impl && ) = default; + Char ** _env_impl = &*_env_arr.begin(); + + native_handle_type native_handle() const {return _buf.get();} +}; + +template<typename Char> +inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_type +{ + Char buf[4096]; + auto size = boost::winapi::get_environment_variable(id, buf, sizeof(buf)); + if (size == 0) //failed + { + auto err = ::boost::winapi::GetLastError(); + if (err == ::boost::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value + return ""; + else + throw process_error(std::error_code(err, std::system_category()), + "GetEnvironmentVariable() failed"); + } + + if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong + { + /*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx + * but I used 32768 so it is a multiple of 4096. + */ + constexpr static std::size_t max_size = 32768; + //Handle variables longer then buf. + std::size_t buf_size = sizeof(buf); + while (buf_size <= max_size) + { + std::vector<Char> buf(buf_size); + auto size = boost::winapi::get_environment_variable(id, buf.data(), buf.size()); + + if (size == buf_size) //buffer to small + buf_size *= 2; + else if (size == 0) + ::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed"); + else + return std::basic_string<Char>( + buf.data(), buf.data()+ size + 1); + + } + + } + return std::basic_string<Char>(buf, buf+size+1); +} + +template<typename Char> +inline void native_environment_impl<Char>::set(const pointer_type id, const pointer_type value) +{ + boost::winapi::set_environment_variable(id, value); +} + +template<typename Char> +inline void native_environment_impl<Char>::reset(const pointer_type id) +{ + boost::winapi::set_environment_variable(id, nullptr); +} + +template<typename Char> +std::vector<Char*> native_environment_impl<Char>::_load_var(Char* p) +{ + std::vector<Char*> ret; + if (*p != null_char<Char>()) + { + ret.push_back(p); + while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>())) + { + if (*p==null_char<Char>()) + { + p++; + ret.push_back(p); + } + else + p++; + } + } + p++; + ret.push_back(nullptr); + + return ret; +} + + +template<typename Char> +struct basic_environment_impl +{ + std::vector<Char> _data = {null_char<Char>()}; + static std::vector<Char*> _load_var(Char* p); + std::vector<Char*> _env_arr{_load_var(_data.data())}; +public: + using char_type = Char; + using pointer_type = const char_type*; + using string_type = std::basic_string<char_type>; + using native_handle_type = pointer_type; + + std::size_t size() const { return _data.size();} + + void reload() + { + _env_arr = _load_var(_data.data()); + _env_impl = _env_arr.data(); + } + + string_type get(const pointer_type id) {return get(string_type(id));} + void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);} + void reset(const pointer_type id) {reset(string_type(id));} + + string_type get(const string_type & id); + void set(const string_type & id, const string_type & value); + void reset(const string_type & id); + + inline basic_environment_impl(const native_environment_impl<Char> & nei); + basic_environment_impl() = default; + basic_environment_impl(const basic_environment_impl& rhs) + : _data(rhs._data) + { + } + basic_environment_impl(basic_environment_impl && rhs) + : _data(std::move(rhs._data)), + _env_arr(std::move(rhs._env_arr)), + _env_impl(_env_arr.data()) + { + } + basic_environment_impl &operator=(basic_environment_impl && rhs) + { + _data = std::move(rhs._data); + //reload(); + _env_arr = std::move(rhs._env_arr); + _env_impl = _env_arr.data(); + + return *this; + } + basic_environment_impl & operator=(const basic_environment_impl& rhs) + { + _data = rhs._data; + reload(); + return *this; + } + + template<typename CharR> + explicit inline basic_environment_impl( + const basic_environment_impl<CharR>& rhs, + const ::boost::process::codecvt_type & cv = ::boost::process::codecvt()) + : _data(::boost::process::detail::convert(rhs._data, cv)) + { + } + + template<typename CharR> + basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs) + { + _data = ::boost::process::detail::convert(rhs._data); + _env_arr = _load_var(&*_data.begin()); + _env_impl = &*_env_arr.begin(); + return *this; + } + + Char ** _env_impl = &*_env_arr.begin(); + + native_handle_type native_handle() const {return &*_data.begin();} +}; + + +template<typename Char> +basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei) +{ + auto beg = nei.native_handle(); + auto p = beg; + while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>())) + p++; + p++; //pointing to the second nullchar + p++; //to get the pointer behing the second nullchar, so it's end. + + this->_data.assign(beg, p); + this->reload(); +} + + +template<typename Char> +inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type +{ + + if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>())) + return string_type(_data.data()); //null-char is handled by the string. + + std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars + seq.insert(seq.end(), id.begin(), id.end()); + seq.push_back('='); + + auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end()); + + if (itr == _data.end()) //not found + return ""; + + itr += seq.size(); //advance to the value behind the '='; the std::string will take care of finding the null-char. + + return string_type(&*itr); +} + +template<typename Char> +inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value) +{ + reset(id); - std::vector<Char> insertion;
+ std::vector<Char> insertion; - insertion.insert(insertion.end(), id.begin(), id.end());
- insertion.push_back('=');
- insertion.insert(insertion.end(), value.begin(), value.end());
- insertion.push_back('\0');
+ insertion.insert(insertion.end(), id.begin(), id.end()); + insertion.push_back('='); + insertion.insert(insertion.end(), value.begin(), value.end()); + insertion.push_back('\0'); - _data.insert(_data.end() -1, insertion.begin(), insertion.end());
+ _data.insert(_data.end() -1, insertion.begin(), insertion.end()); - reload();
-}
+ reload(); +} -template<typename Char>
-inline void basic_environment_impl<Char>::reset(const string_type &id)
-{
- //ok, we need to check the size of data first
- if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
- return;
+template<typename Char> +inline void basic_environment_impl<Char>::reset(const string_type &id) +{ + //ok, we need to check the size of data first + if (id.size() >= _data.size()) //ok, so it's impossible id is in there. + return; - //check if it's the first one, spares us the search.
- if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
- {
- auto beg = _data.begin();
- auto end = beg;
+ //check if it's the first one, spares us the search. + if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>())) + { + auto beg = _data.begin(); + auto end = beg; - while (*end != '\0')
- end++;
+ while (*end != '\0') + end++; - end++; //to point behind the last null-char
+ end++; //to point behind the last null-char - _data.erase(beg, end); //and remove the thingy
+ _data.erase(beg, end); //and remove the thingy - }
+ } - std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
- seq.insert(seq.end(), id.begin(), id.end());
- seq.push_back('=');
+ std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars + seq.insert(seq.end(), id.begin(), id.end()); + seq.push_back('='); - auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
+ auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end()); - if (itr == _data.end())
- return;//nothing to return if it's empty anyway...
+ if (itr == _data.end()) + return;//nothing to return if it's empty anyway... - auto end = itr;
+ auto end = itr; - while (*end != '\0')
- end++;
+ while (*++end != '\0'); - end ++; //to point behind the last null-char
- _data.erase(itr, end);//and remove it
- reload();
+ _data.erase(itr, end);//and remove it + reload(); -}
+} -template<typename Char>
-std::vector<Char*> basic_environment_impl<Char>::_load_var(Char* p)
-{
- std::vector<Char*> ret;
- if (*p != null_char<Char>())
- {
- ret.push_back(p);
- while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
- {
- if (*p==null_char<Char>())
- {
- p++;
- ret.push_back(p);
- }
- else
- p++;
- }
- }
- p++;
- ret.push_back(nullptr);
- return ret;
-}
+template<typename Char> +std::vector<Char*> basic_environment_impl<Char>::_load_var(Char* p) +{ + std::vector<Char*> ret; + if (*p != null_char<Char>()) + { + ret.push_back(p); + while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>())) + { + if (*p==null_char<Char>()) + { + p++; + ret.push_back(p); + } + else + p++; + } + } + p++; + ret.push_back(nullptr); + return ret; +} -template<typename T> constexpr T env_seperator();
-template<> constexpr char env_seperator() {return ';'; }
-template<> constexpr wchar_t env_seperator() {return L';'; }
+template<typename T> constexpr T env_seperator(); +template<> constexpr char env_seperator() {return ';'; } +template<> constexpr wchar_t env_seperator() {return L';'; } -inline int get_id() {return boost::detail::winapi::GetCurrentProcessId();}
-inline void* native_handle() {return boost::detail::winapi::GetCurrentProcess(); }
+inline int get_id() {return boost::winapi::GetCurrentProcessId();} +inline void* native_handle() {return boost::winapi::GetCurrentProcess(); } -typedef void* native_handle_t;
+typedef void* native_handle_t; -}
+} -}
-}
-}
+} +} +} -#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */ |