328 lines
9.8 KiB
C++
328 lines
9.8 KiB
C++
|
// 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_POSIX_ENVIRONMENT_HPP_
|
||
|
#define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
|
||
|
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
#include <unordered_map>
|
||
|
#include <boost/process/detail/config.hpp>
|
||
|
#include <algorithm>
|
||
|
#include <cstdlib>
|
||
|
#include <boost/process/locale.hpp>
|
||
|
|
||
|
|
||
|
namespace boost { namespace process { namespace detail { namespace posix {
|
||
|
|
||
|
template<typename Char>
|
||
|
class native_environment_impl
|
||
|
{
|
||
|
static std::vector<std::basic_string<Char>> _load()
|
||
|
{
|
||
|
std::vector<std::basic_string<Char>> val;
|
||
|
auto p = environ;
|
||
|
while (*p != nullptr)
|
||
|
{
|
||
|
std::string str = *p;
|
||
|
val.push_back(::boost::process::detail::convert(str));
|
||
|
p++;
|
||
|
}
|
||
|
return val;
|
||
|
}
|
||
|
static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
|
||
|
{
|
||
|
std::vector<Char*> val;
|
||
|
val.resize(vec.size() + 1);
|
||
|
std::transform(vec.begin(), vec.end(), val.begin(),
|
||
|
[](std::basic_string<Char> & str)
|
||
|
{
|
||
|
return &str.front();
|
||
|
});
|
||
|
val.back() = nullptr;
|
||
|
return val;
|
||
|
}
|
||
|
std::vector<std::basic_string<Char>> _buffer = _load();
|
||
|
std::vector<Char*> _impl = _load_var(_buffer);
|
||
|
public:
|
||
|
using char_type = Char;
|
||
|
using pointer_type = const char_type*;
|
||
|
using string_type = std::basic_string<char_type>;
|
||
|
using native_handle_type = char_type **;
|
||
|
|
||
|
void reload()
|
||
|
{
|
||
|
_buffer = _load();
|
||
|
_impl = _load_var(_buffer);
|
||
|
_env_impl = _impl.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), string_type(value));
|
||
|
}
|
||
|
void reset(const pointer_type id) { reset(string_type(id)); }
|
||
|
|
||
|
string_type get(const string_type & id)
|
||
|
{
|
||
|
std::string id_c = ::boost::process::detail::convert(id);
|
||
|
std::string g = ::getenv(id_c.c_str());
|
||
|
return ::boost::process::detail::convert(g.c_str());
|
||
|
}
|
||
|
void set(const string_type & id, const string_type & value)
|
||
|
{
|
||
|
std::string id_c = ::boost::process::detail::convert(id.c_str());
|
||
|
std::string value_c = ::boost::process::detail::convert(value.c_str());
|
||
|
auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
|
||
|
if (res != 0)
|
||
|
boost::process::detail::throw_last_error();
|
||
|
}
|
||
|
void reset(const string_type & id)
|
||
|
{
|
||
|
std::string id_c = ::boost::process::detail::convert(id.c_str());
|
||
|
auto res = ::unsetenv(id_c.c_str());
|
||
|
if (res != 0)
|
||
|
::boost::process::detail::throw_last_error();
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
native_handle_type _env_impl = _impl.data();
|
||
|
|
||
|
native_handle_type native_handle() const {return _env_impl;}
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
class native_environment_impl<char>
|
||
|
{
|
||
|
public:
|
||
|
using char_type = char;
|
||
|
using pointer_type = const char_type*;
|
||
|
using string_type = std::basic_string<char_type>;
|
||
|
using native_handle_type = char_type **;
|
||
|
|
||
|
void reload() {this->_env_impl = ::environ;}
|
||
|
|
||
|
string_type get(const pointer_type id) { return getenv(id); }
|
||
|
void set(const pointer_type id, const pointer_type value)
|
||
|
{
|
||
|
auto res = ::setenv(id, value, 1);
|
||
|
if (res != 0)
|
||
|
boost::process::detail::throw_last_error();
|
||
|
reload();
|
||
|
}
|
||
|
void reset(const pointer_type id)
|
||
|
{
|
||
|
auto res = ::unsetenv(id);
|
||
|
if (res != 0)
|
||
|
boost::process::detail::throw_last_error();
|
||
|
reload();
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
native_handle_type _env_impl = environ;
|
||
|
|
||
|
native_handle_type native_handle() const {return ::environ;}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
template<typename Char>
|
||
|
struct basic_environment_impl
|
||
|
{
|
||
|
std::vector<std::basic_string<Char>> _data {};
|
||
|
static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
|
||
|
std::vector<Char*> _env_arr{_load_var(_data)};
|
||
|
public:
|
||
|
using char_type = Char;
|
||
|
using pointer_type = const char_type*;
|
||
|
using string_type = std::basic_string<char_type>;
|
||
|
using native_handle_type = Char**;
|
||
|
void reload()
|
||
|
{
|
||
|
_env_arr = _load_var(_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);
|
||
|
|
||
|
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 && ) = default;
|
||
|
basic_environment_impl & operator=(const basic_environment_impl& rhs)
|
||
|
{
|
||
|
_data = rhs._data;
|
||
|
_env_arr = _load_var(_data);
|
||
|
_env_impl = &*_env_arr.begin();
|
||
|
return *this;
|
||
|
}
|
||
|
basic_environment_impl & operator=(basic_environment_impl && ) = default;
|
||
|
|
||
|
template<typename CharR>
|
||
|
explicit inline basic_environment_impl(
|
||
|
const basic_environment_impl<CharR>& rhs,
|
||
|
const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
|
||
|
: _data(rhs._data.size())
|
||
|
{
|
||
|
std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
|
||
|
[&](const std::basic_string<CharR> & st)
|
||
|
{
|
||
|
return ::boost::process::detail::convert(st, cv);
|
||
|
}
|
||
|
|
||
|
);
|
||
|
reload();
|
||
|
}
|
||
|
|
||
|
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.data();
|
||
|
|
||
|
native_handle_type native_handle() const {return &_data.front();}
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename Char>
|
||
|
basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
|
||
|
{
|
||
|
auto beg = nei.native_handle();
|
||
|
|
||
|
auto end = beg;
|
||
|
while (*end != nullptr)
|
||
|
end++;
|
||
|
this->_data.assign(beg, end);
|
||
|
reload();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<typename Char>
|
||
|
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
|
||
|
{
|
||
|
auto itr = std::find_if(_data.begin(), _data.end(),
|
||
|
[&](const string_type & st) -> bool
|
||
|
{
|
||
|
if (st.size() <= id.size())
|
||
|
return false;
|
||
|
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
|
||
|
}
|
||
|
);
|
||
|
|
||
|
if (itr == _data.end())
|
||
|
{
|
||
|
return "";
|
||
|
}
|
||
|
else return
|
||
|
itr->data() + id.size(); //id=Thingy -> +2 points to T
|
||
|
}
|
||
|
|
||
|
template<typename Char>
|
||
|
inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
|
||
|
{
|
||
|
auto itr = std::find_if(_data.begin(), _data.end(),
|
||
|
[&](const string_type & st) -> bool
|
||
|
{
|
||
|
if (st.size() <= id.size())
|
||
|
return false;
|
||
|
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
|
||
|
}
|
||
|
);
|
||
|
|
||
|
if (itr != _data.end())
|
||
|
*itr = id + equal_sign<Char>() + value;
|
||
|
else
|
||
|
_data.push_back(id + equal_sign<Char>() + value);
|
||
|
|
||
|
reload();
|
||
|
}
|
||
|
|
||
|
template<typename Char>
|
||
|
inline void basic_environment_impl<Char>::reset(const string_type &id)
|
||
|
{
|
||
|
auto itr = std::find_if(_data.begin(), _data.end(),
|
||
|
[&](const string_type & st) -> bool
|
||
|
{
|
||
|
if (st.size() <= id.size())
|
||
|
return false;
|
||
|
return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
|
||
|
}
|
||
|
);
|
||
|
if (itr != _data.end())
|
||
|
{
|
||
|
_data.erase(itr);//and remove it
|
||
|
}
|
||
|
|
||
|
reload();
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
template<typename Char>
|
||
|
std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
|
||
|
{
|
||
|
std::vector<Char*> ret;
|
||
|
ret.reserve(data.size() +1);
|
||
|
|
||
|
for (auto & val : data)
|
||
|
{
|
||
|
if (val.empty())
|
||
|
val.push_back(0);
|
||
|
ret.push_back(&val.front());
|
||
|
}
|
||
|
|
||
|
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':'; }
|
||
|
|
||
|
|
||
|
typedef int native_handle_t;
|
||
|
|
||
|
inline int get_id() {return getpid(); }
|
||
|
inline int native_handle() {return getpid(); }
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
|