summaryrefslogtreecommitdiff
path: root/boost/process/detail/windows/environment.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/process/detail/windows/environment.hpp')
-rw-r--r--boost/process/detail/windows/environment.hpp650
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_ */