Elements  5.12.0
A C++ base framework for the Euclid Software.
Environment.cpp
Go to the documentation of this file.
1 
23 
24 #include <string> // for string
25 #include <sstream> // for stringstream
26 #include <stdexcept> // for out_of_range
27 #include <algorithm> // for find
28 #include <utility> // for move
29 #include <map> // for map
30 
31 #include <boost/format.hpp> // for format
32 
33 #include "ElementsKernel/System.h" // for getEnv, setEnv, isEnvSet
34 
35 using std::string;
36 using std::stringstream;
37 using std::ostream;
38 using std::endl;
39 
40 namespace Elements {
41 
42 using System::unSetEnv;
43 using System::setEnv;
44 using System::getEnv;
45 using System::isEnvSet;
46 
47 Environment::Variable::Variable(Environment& arg_env, const string& arg_index): m_env{arg_env}, m_index{arg_index} {
48 }
49 
50 Environment::Variable::Variable(const Environment::Variable& other): m_env{other.m_env} {
51 
52  checkCompatibility(other);
53 
54 }
55 
56 Environment::Variable::Variable(Environment::Variable&& other): m_env{std::move(other.m_env)} {
57 
58  checkCompatibility(other);
59 
60 }
61 
63 
64  checkCompatibility(other);
65 
66  m_env = other.m_env;
67 
68  return *this;
69 }
70 
72 
73  checkCompatibility(other);
74 
75  m_env = move(other.m_env);
76 
77  return *this;
78 }
79 
80 
82 
83  set(arg_value);
84 
85  return *this;
86 }
87 
89 
90  m_env.get().set(m_index, arg_value);
91 
92  return *this;
93 }
94 
96 
97  m_env.get().unSet(m_index);
98 
99  return *this;
100 }
101 
103 
104  m_env.get().append(m_index, arg_value);
105 
106  return *this;
107 }
108 
110 
111  return append(arg_value);
112 
113 }
114 
116 
117  m_env.get().prepend(m_index, arg_value);
118 
119  return *this;
120 }
121 
123 
124  Environment::Variable result(m_env, m_index);
125 
126  result.append(arg_value);
127 
128  return result;
129 }
130 
131 
132 const string& Environment::Variable::index() const {
133  return m_index;
134 }
135 
137  return m_env;
138 }
139 
140 
142 
143  return m_env.get().get(m_index, "");
144 
145 }
146 
147 Environment::Variable::operator std::string() const {
148  return value();
149 }
150 
152  return value().empty();
153 }
154 
156  return m_env.get().hasKey(m_index);
157 }
158 
160 
161  if (m_index != other.m_index) {
162  stringstream error_buffer;
163  error_buffer << "The \"" << other.m_index << "\" environment variable"
164  << " cannot be copied to the \"" << m_index << "\" environment variable."
165  << endl;
166  throw std::invalid_argument(error_buffer.str());
167  }
168 
169 }
170 
171 
172 //----------------------------------------------------------------------------
173 
175  : m_old_values{}, m_keep_same{keep_same}, m_added_variables{} {
176 
177 }
178 
180 
181  for (const auto& v : m_added_variables) {
182  unSetEnv(v);
183  }
184 
185  for (const auto& v : m_old_values) {
186  setEnv(v.first, v.second);
187  }
188 
189  m_old_values = {};
190 
191  return *this;
192 }
193 
194 
196  restore();
197 }
198 
200 
201  return Environment::Variable(*this, index);
202 
203 }
204 
205 const Environment::Variable Environment::operator[](const string& index) const {
206 
207  return Environment::Variable(const_cast<Environment&>(*this), index);
208 
209 }
210 
211 Environment& Environment::set(const string& index, const string& value) {
212 
213  if (m_old_values.find(index) == m_old_values.end()) {
214  if (hasKey(index)) {
215  if ((not m_keep_same) || (getEnv(index) != value)) {
216  m_old_values[index] = getEnv(index);
217  }
218  } else {
220  }
221  }
222 
223  setEnv(index, value);
224 
225  return *this;
226 
227 }
228 
229 Environment& Environment::unSet(const string& index) {
230 
231  checkOutOfRange(index);
232 
233  if (m_old_values.find(index) == m_old_values.end()) {
234  auto found_index = std::find(m_added_variables.begin(), m_added_variables.end(), index);
235  if (found_index != m_added_variables.end()) {
236  m_added_variables.erase(found_index);
237  } else {
238  m_old_values[index] = getEnv(index);
239  }
240  }
241 
242  unSetEnv(index);
243 
244  return *this;
245 
246 }
247 
248 Environment& Environment::append(const string& index, const string& value) {
249 
250  const string new_value = get(index) + value;
251 
252  set(index, new_value);
253 
254  return *this;
255 }
256 
257 Environment& Environment::prepend(const string& index, const string& value) {
258 
259  const string new_value = value + get(index);
260 
261  set(index, new_value);
262 
263  return *this;
264 }
265 
266 string Environment::get(const string& index, const string& default_value) const {
267  string value {default_value};
268 
269  if (hasKey(index)) {
270  value = getEnv(index);
271  }
272 
273  return value;
274 }
275 
276 bool Environment::hasKey(const string& index) {
277 
278  return isEnvSet(index);
279 
280 }
281 
283 
284  m_old_values = {};
285  m_added_variables = {};
286 
287 }
288 
290 
291  using std::map;
292  using boost::format;
293 
294  stringstream script_text {};
295 
296  map<ShellType, string> set_cmd {{ShellType::sh, "export %s=%s"},
297  {ShellType::csh, "setenv %s %s"}};
298  map<ShellType, string> unset_cmd {{ShellType::sh, "unset %s"},
299  {ShellType::csh, "unsetenv %s"}};
300 
301  for (const auto& v : m_old_values) {
302  if (hasKey(v.first)) {
303  script_text << format(set_cmd[type]) % v.first % get(v.first) << endl;
304  } else {
305  script_text << format(unset_cmd[type]) % v.first << endl;
306  }
307  }
308 
309  for (const auto& v : m_added_variables) {
310  script_text << format(set_cmd[type]) % v % get(v) << endl;
311  }
312 
313  return script_text.str();
314 
315 }
316 
317 
318 void Environment::checkOutOfRange(const string& index) {
319 
320  if (not hasKey(index)) {
321  stringstream error_buffer;
322  error_buffer << "The environment doesn't contain the " << index << " variable." << endl;
323  throw std::out_of_range(error_buffer.str());
324  }
325 
326 }
327 
329 
330  stream << v.value();
331 
332  return stream;
333 
334 }
335 
336 Environment::Variable operator+(const string& value, const Environment::Variable& other) {
337 
338  Environment::Variable result(other.env(), other.index());
339 
340  result.prepend(value);
341 
342  return result;
343 
344 }
345 
346 } // namespace Elements
Defines a class to handle the Environment.
This file is intended to iron out all the differences between systems (currently Linux and MacOSX)
T begin(T... args)
proxy class to overload the assignment
Definition: Environment.h:91
Variable & operator=(const Variable &other)
Definition: Environment.cpp:62
Variable & set(const std::string &)
Definition: Environment.cpp:88
Variable & operator+=(const std::string &)
std::reference_wrapper< Environment > m_env
a copiable and movable reference
Definition: Environment.h:120
Variable & prepend(const std::string &)
std::string m_index
The Name of the variable.
Definition: Environment.h:123
Variable & append(const std::string &)
void checkCompatibility(const Variable &)
Variable operator+(const std::string &)
const std::string & index() const
Environment & env() const
std::vector< std::string > m_added_variables
variable added to the environment
Definition: Environment.h:83
std::string get(const std::string &index, const std::string &default_value="") const
Variable operator[](const std::string &)
Environment(bool keep_same=true)
std::map< std::string, std::string > m_old_values
old value for changed variables
Definition: Environment.h:78
static bool hasKey(const std::string &)
Environment & set(const std::string &, const std::string &)
Environment & append(const std::string &, const std::string &)
Environment & unSet(const std::string &)
Environment & restore()
Environment & prepend(const std::string &, const std::string &)
std::string generateScript(ShellType) const
T emplace_back(T... args)
T end(T... args)
T endl(T... args)
T erase(T... args)
T find(T... args)
static void checkOutOfRange(const std::string &)
check that the variable is in the environment
ELEMENTS_API bool isEnvSet(const std::string &var)
Check if an environment variable is set or not.
Definition: System.cpp:355
ELEMENTS_API int setEnv(const std::string &name, const std::string &value, bool overwrite=true)
set an environment variables.
Definition: System.cpp:377
ELEMENTS_API int unSetEnv(const std::string &name)
Simple wrap around unsetenv for strings.
Definition: System.cpp:388
ELEMENTS_API std::string getEnv(const std::string &var)
get a particular environment variable
Definition: System.cpp:331
ELEMENTS_API Environment::Variable operator+(const std::string &, const Environment::Variable &)
ELEMENTS_API std::ostream & operator<<(std::ostream &, const Environment::Variable &)
STL namespace.
T str(T... args)